From a89d667f85d01ec5dc5353835dc6a56696479801 Mon Sep 17 00:00:00 2001 From: <> Date: Fri, 23 Aug 2024 15:52:24 +0000 Subject: [PATCH] Deployed 2420d974 with MkDocs version: 1.5.0 --- api_reference/trestle.common.const/index.html | 32 ++ .../index.html | 42 ++- .../index.html | 8 +- .../index.html | 15 +- .../trestle.core.control_context/index.html | 46 ++- .../trestle.core.control_interface/index.html | 47 ++- .../trestle.core.control_writer/index.html | 68 ++-- .../trestle.core.repository/index.html | 64 ++-- .../index.html | 30 +- contributing/mkdocs_contributing/index.html | 1 - maintainers/index.html | 1 - mkdocs_code_of_conduct/index.html | 3 +- objects.inv | Bin 33592 -> 33616 bytes search/search_index.json | 2 +- sitemap.xml | 298 +++++++++--------- sitemap.xml.gz | Bin 1401 -> 1400 bytes .../ssp_profile_catalog_authoring/index.html | 1 + 17 files changed, 416 insertions(+), 242 deletions(-) diff --git a/api_reference/trestle.common.const/index.html b/api_reference/trestle.common.const/index.html index 6939951b0..965a04260 100644 --- a/api_reference/trestle.common.const/index.html +++ b/api_reference/trestle.common.const/index.html @@ -1716,6 +1716,13 @@ HELP_FO_OUTPUT + + +
  • + + HELP_INCLUDE_ALL_PARTS + +
  • @@ -6564,6 +6571,13 @@ HELP_FO_OUTPUT +
  • + +
  • + + HELP_INCLUDE_ALL_PARTS + +
  • @@ -8896,6 +8910,24 @@

    +

    +HELP_INCLUDE_ALL_PARTS + + +¤

    + +
    + +
    + + + + + +
    + + +

    HELP_LEVERAGED diff --git a/api_reference/trestle.core.catalog.catalog_reader/index.html b/api_reference/trestle.core.catalog.catalog_reader/index.html index c6405d0c4..66b3a710e 100644 --- a/api_reference/trestle.core.catalog.catalog_reader/index.html +++ b/api_reference/trestle.core.catalog.catalog_reader/index.html @@ -4880,30 +4880,45 @@

    ssp.control_implementation.implemented_requirements ) ssp.control_implementation.implemented_requirements.append(control_imp_req) + CatalogReader._add_statement_to_impl_requirement(control_imp_req, statement_id) + return control_imp_req + + @staticmethod + def _add_statement_to_impl_requirement(impl_req: ossp.ImplementedRequirement, statement_id: str) -> ossp.Statement: + """Update the implemented requirement with a new statement.""" statement = gens.generate_sample_model(ossp.Statement) statement.statement_id = statement_id statement.by_components = None - control_imp_req.statements = as_list(control_imp_req.statements) - control_imp_req.statements.append(statement) - return control_imp_req + impl_req.statements = as_list(impl_req.statements) + impl_req.statements.append(statement) + return statement @staticmethod def _get_by_comp_from_imp_req( imp_req: ossp.ImplementedRequirement, statement_id: str, comp_uuid: str ) -> ossp.ByComponent: if statement_id: + found_statement: Optional[ossp.Statement] = None for statement in as_list(imp_req.statements): if statement.statement_id == statement_id: - for by_comp in as_list(statement.by_components): - if by_comp.component_uuid == comp_uuid: - return by_comp - # didnt find bycomp so need to make one - by_comp = gens.generate_sample_model(ossp.ByComponent) - by_comp.component_uuid = comp_uuid - by_comp.implementation_status = com.ImplementationStatus(state=const.STATUS_PLANNED) - statement.by_components = as_list(statement.by_components) - statement.by_components.append(by_comp) - return by_comp + found_statement = statement + break + + # If the statement doesn't exist, create it + if not found_statement: + found_statement = CatalogReader._add_statement_to_impl_requirement(imp_req, statement_id) + else: + for by_comp in as_list(found_statement.by_components): + if by_comp.component_uuid == comp_uuid: + return by_comp + + # didnt find bycomp or new statement so need to make one + by_comp = gens.generate_sample_model(ossp.ByComponent) + by_comp.component_uuid = comp_uuid + by_comp.implementation_status = com.ImplementationStatus(state=const.STATUS_PLANNED) + found_statement.by_components = as_list(found_statement.by_components) + found_statement.by_components.append(by_comp) + return by_comp else: for by_comp in as_list(imp_req.by_components): if by_comp.component_uuid == comp_uuid: @@ -4914,7 +4929,6 @@

    imp_req.by_components = as_list(imp_req.by_components) imp_req.by_components.append(by_comp) return by_comp - raise TrestleError(f'Internal error seeking by_comp for component {comp_uuid} and statement {statement_id}') @staticmethod def _read_comp_info_from_md(control_file_path: pathlib.Path, diff --git a/api_reference/trestle.core.catalog.catalog_writer/index.html b/api_reference/trestle.core.catalog.catalog_writer/index.html index 8247591a1..8c8926b76 100644 --- a/api_reference/trestle.core.catalog.catalog_writer/index.html +++ b/api_reference/trestle.core.catalog.catalog_writer/index.html @@ -4847,9 +4847,11 @@

    # adds it to prof-param-value-origin if prof_param_value_origin != '' and prof_param_value_origin is not None: if context.purpose == ContextPurpose.PROFILE: - new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = prof_param_value_origin + if const.AGGREGATES not in [prop.name for prop in as_list(param.props)]: + new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = prof_param_value_origin else: - new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = const.REPLACE_ME_PLACEHOLDER + if const.AGGREGATES not in [prop.name for prop in as_list(param.props)]: + new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = const.REPLACE_ME_PLACEHOLDER # then insert the original, incoming values as values if param_id in control_param_dict: orig_param = control_param_dict[param_id] @@ -4862,6 +4864,8 @@

    new_dict.pop(const.VALUES) if new_dict[const.GUIDELINES] is None: new_dict.pop(const.GUIDELINES) + if const.AGGREGATES in [prop.name for prop in as_list(orig_param.props)]: + new_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN) else: # if the profile doesnt change this param at all, show it in the header with values tmp_dict = ModelUtils.parameter_to_dict(param_dict, True) diff --git a/api_reference/trestle.core.commands.author.ssp/index.html b/api_reference/trestle.core.commands.author.ssp/index.html index 763b9aa20..315d81f33 100644 --- a/api_reference/trestle.core.commands.author.ssp/index.html +++ b/api_reference/trestle.core.commands.author.ssp/index.html @@ -5884,6 +5884,14 @@

    action='store_true', default=False ) + self.add_argument( + '-iap', + '--include-all-parts', + help=const.HELP_INCLUDE_ALL_PARTS, + required=False, + action='store_true', + default=False + ) def _run(self, args: argparse.Namespace) -> int: try: @@ -5913,7 +5921,8 @@

    md_path, yaml_header, args.overwrite_header_values, - args.force_overwrite + args.force_overwrite, + args.include_all_parts ) except Exception as e: # pragma: no cover @@ -5928,7 +5937,8 @@

    md_path: pathlib.Path, yaml_header: Dict[str, Any], overwrite_header_values: bool, - force_overwrite: bool + force_overwrite: bool, + include_all_parts: bool ) -> int: """ Generate the ssp markdown from the profile and compdefs. @@ -5960,6 +5970,7 @@

    context.overwrite_header_values = overwrite_header_values context.allowed_sections = None context.comp_def_name_list = compdef_name_list + context.include_all_parts = include_all_parts # if file not recognized as URI form, assume it represents name of file in trestle directory profile_in_trestle_dir = '://' not in profile_name_or_href diff --git a/api_reference/trestle.core.control_context/index.html b/api_reference/trestle.core.control_context/index.html index aa04b8bcc..eec0cef45 100644 --- a/api_reference/trestle.core.control_context/index.html +++ b/api_reference/trestle.core.control_context/index.html @@ -2690,6 +2690,13 @@ control_implementation +

  • + +
  • + + include_all_parts + +
  • @@ -4853,6 +4860,13 @@ control_implementation +
  • + +
  • + + include_all_parts + +
  • @@ -5218,6 +5232,7 @@

    trestle_root: pathlib.Path md_root: pathlib.Path prompt_responses: bool + include_all_parts: bool overwrite_header_values: bool set_parameters_flag: bool cli_yaml_header: Optional[Dict[Any, Any]] = None @@ -5245,6 +5260,7 @@

    trestle_root: pathlib.Path, md_root: pathlib.Path, prompt_responses: bool = False, + include_all_parts: bool = False, overwrite_header_values: bool = False, set_parameters_flag: bool = False, cli_yaml_header: Optional[Dict[Any, Any]] = None, @@ -5271,6 +5287,7 @@

    trestle_root, md_root, prompt_responses, + include_all_parts, overwrite_header_values, set_parameters_flag, cli_yaml_header=cli_yaml_header, @@ -5306,6 +5323,7 @@

    context.trestle_root, context.md_root, context.prompt_responses, + context.include_all_parts, context.overwrite_header_values, context.set_parameters_flag, cli_yaml_header=copy.deepcopy(context.cli_yaml_header), @@ -5510,6 +5528,27 @@

    +include_all_parts: bool + + + dataclass-field + + +¤
    + +
    + +
    + + + + + +
    + + +
    inherited_props: Optional[Dict[str, Any]] @@ -5851,7 +5890,7 @@
    -__init__(self, purpose, to_markdown, trestle_root, md_root, prompt_responses, overwrite_header_values, set_parameters_flag, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) +__init__(self, purpose, to_markdown, trestle_root, md_root, prompt_responses, include_all_parts, overwrite_header_values, set_parameters_flag, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) special @@ -5918,6 +5957,7 @@
    context.trestle_root, context.md_root, context.prompt_responses, + context.include_all_parts, context.overwrite_header_values, context.set_parameters_flag, cli_yaml_header=copy.deepcopy(context.cli_yaml_header), @@ -5951,7 +5991,7 @@
    -generate(purpose, to_markdown, trestle_root, md_root, prompt_responses=False, overwrite_header_values=False, set_parameters_flag=False, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) +generate(purpose, to_markdown, trestle_root, md_root, prompt_responses=False, include_all_parts=False, overwrite_header_values=False, set_parameters_flag=False, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) classmethod @@ -5973,6 +6013,7 @@
    trestle_root: pathlib.Path, md_root: pathlib.Path, prompt_responses: bool = False, + include_all_parts: bool = False, overwrite_header_values: bool = False, set_parameters_flag: bool = False, cli_yaml_header: Optional[Dict[Any, Any]] = None, @@ -5999,6 +6040,7 @@
    trestle_root, md_root, prompt_responses, + include_all_parts, overwrite_header_values, set_parameters_flag, cli_yaml_header=cli_yaml_header, diff --git a/api_reference/trestle.core.control_interface/index.html b/api_reference/trestle.core.control_interface/index.html index a58ce04bc..6dd3e4a2f 100644 --- a/api_reference/trestle.core.control_interface/index.html +++ b/api_reference/trestle.core.control_interface/index.html @@ -6377,6 +6377,24 @@

    return choices_str return '' + @staticmethod + def _param_as_aggregated_value( + param: common.Parameter, + param_dict: Dict[str, common.Parameter], + verbose: bool = False, + brackets: bool = False + ) -> str: + """Convert parameter aggregation to str.""" + # review is an aggregated parameter + if const.AGGREGATES in [prop.name for prop in as_list(param.props)]: + aggregated_values = '' + for prop in as_list(param.props): + if prop.value not in param_dict: + continue + aggregated_values += ', '.join(as_list(param_dict[prop.value].values)) + ', ' + return aggregated_values[:-2] + return '' + @staticmethod def _param_label_choices_as_str(param: common.Parameter, verbose: bool = False, brackets: bool = False) -> str: """Convert param label or choices to string, using choices if present.""" @@ -6388,6 +6406,7 @@

    @staticmethod def _param_values_assignment_str( param: common.Parameter, + param_dict: Dict[str, common.Parameter], value_assigned_prefix: Optional[str] = None, value_not_assigned_prefix: Optional[str] = None ) -> str: @@ -6399,6 +6418,9 @@

    # otherwise use param selection if present if not param_str: param_str = ControlInterface._param_selection_as_str(param, True, False) + # otherwise use param aggregated values if present + if not param_str: + param_str = ControlInterface._param_as_aggregated_value(param, param_dict, True, False) # finally use label and param_id as fallbacks if not param_str: param_str = param.label if param.label else param.id @@ -6429,7 +6451,8 @@

    brackets: bool = False, params_format: Optional[str] = None, value_assigned_prefix: Optional[str] = None, - value_not_assigned_prefix: Optional[str] = None + value_not_assigned_prefix: Optional[str] = None, + param_dict: Dict[str, common.Parameter] = None ) -> Optional[str]: """ Convert parameter to string based on best available representation. @@ -6462,7 +6485,7 @@

    param_str = '' elif param_rep == ParameterRep.ASSIGNMENT_FORM: param_str = ControlInterface._param_values_assignment_str( - param, value_assigned_prefix, value_not_assigned_prefix + param, param_dict, value_assigned_prefix, value_not_assigned_prefix ) if not param_str: param_str = '' @@ -6561,11 +6584,20 @@

    elif param_dict[param_ids[i]] is not None: param = param_dict[param_ids[i]] param_str = ControlInterface.param_to_str( - param, param_rep, False, False, params_format, value_assigned_prefix, value_not_assigned_prefix + param, + param_rep, + False, + False, + params_format, + value_assigned_prefix, + value_not_assigned_prefix, + param_dict ) text = text.replace(staches[i], param_str, 1).strip() if show_value_warnings and param_rep != ParameterRep.LABEL_OR_CHOICES and not param.values: - logger.warning(f'Parameter {param_id} has no values and was referenced by prose.') + # verifies the current parameter is not an aggregated parameter to throw a warning + if const.AGGREGATES not in [prop.name for prop in as_list(param.props)]: + logger.warning(f'Parameter {param_id} has no values and was referenced by prose.') elif show_value_warnings: logger.warning(f'Control prose references param {param_ids[i]} with no specified value.') # there may be staches remaining that we can't replace if not in param_dict @@ -8364,7 +8396,7 @@

    -param_to_str(param, param_rep, verbose=False, brackets=False, params_format=None, value_assigned_prefix=None, value_not_assigned_prefix=None) +param_to_str(param, param_rep, verbose=False, brackets=False, params_format=None, value_assigned_prefix=None, value_not_assigned_prefix=None, param_dict=None) staticmethod @@ -8456,7 +8488,8 @@
    brackets: bool = False, params_format: Optional[str] = None, value_assigned_prefix: Optional[str] = None, - value_not_assigned_prefix: Optional[str] = None + value_not_assigned_prefix: Optional[str] = None, + param_dict: Dict[str, common.Parameter] = None ) -> Optional[str]: """ Convert parameter to string based on best available representation. @@ -8489,7 +8522,7 @@
    param_str = '' elif param_rep == ParameterRep.ASSIGNMENT_FORM: param_str = ControlInterface._param_values_assignment_str( - param, value_assigned_prefix, value_not_assigned_prefix + param, param_dict, value_assigned_prefix, value_not_assigned_prefix ) if not param_str: param_str = '' diff --git a/api_reference/trestle.core.control_writer/index.html b/api_reference/trestle.core.control_writer/index.html index 2b48dc722..4e50bbfd5 100644 --- a/api_reference/trestle.core.control_writer/index.html +++ b/api_reference/trestle.core.control_writer/index.html @@ -4781,6 +4781,22 @@

    else: self._insert_status(ImplementationStatus(state=const.STATUS_PLANNED), level) + def _process_main_component(self, part_id: str, part_label: str, comp_dict: CompDict) -> None: + """Handle prompts for This System component.""" + self._md_file.new_paragraph() + self._md_file.new_header(3, const.SSP_MAIN_COMP_NAME) + self._md_file.new_paragraph() + prose = f'{const.SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT}: {part_id} -->' + status = ImplementationStatus(state=const.STATUS_PLANNED) + sys_comp_dict: Dict[str, ComponentImpInfo] = comp_dict.get(const.SSP_MAIN_COMP_NAME, {}) + if sys_comp_dict and part_label in sys_comp_dict: + comp_info = sys_comp_dict[part_label] + if comp_info.prose: + prose = comp_info.prose + status = comp_info.status + self._md_file.new_paraline(prose) + self._insert_status(status, 4) + def _add_component_control_prompts(self, control_id: str, comp_dict: CompDict, context: ControlContext) -> bool: """Add prompts to the markdown for the control itself, per component.""" if context.purpose not in [ContextPurpose.COMPONENT, ContextPurpose.SSP]: @@ -4790,19 +4806,10 @@

    did_write = False # do special handling for This System if context.purpose == ContextPurpose.SSP: - self._md_file.new_paragraph() - self._md_file.new_header(3, const.SSP_MAIN_COMP_NAME) - self._md_file.new_paragraph() - prose = f'{const.SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT}: {control_id} -->' - status = ImplementationStatus(state=const.STATUS_PLANNED) - if const.SSP_MAIN_COMP_NAME in comp_dict: - comp_info = list(comp_dict[const.SSP_MAIN_COMP_NAME].values())[0] - if comp_info.prose: - prose = comp_info.prose - status = comp_info.status - self._md_file.new_paraline(prose) - self._insert_status(status, 4) + # Passing in the control id and the empty key ('') for the label + self._process_main_component(control_id, '', comp_dict) did_write = True + sorted_comp_names = sorted(comp_dict.keys()) for comp_name in sorted_comp_names: dic = comp_dict[comp_name] @@ -4848,14 +4855,11 @@

    # if no label guess the label from the sub-part id part_label = ControlInterface.get_label(prt) part_label = prt.id.split('.')[-1] if not part_label else part_label - # only write out part if rules apply to it - rules_apply = False - for _, dic in comp_dict.items(): - if part_label in dic and dic[part_label].rules: - rules_apply = True - break - if not rules_apply: + + # Determine if this part should be written out + if self._skip_part(context, part_label, comp_dict): continue + if not did_write_part: self._md_file.new_line(const.SSP_MD_LEAVE_BLANK_TEXT) # insert extra line to make mdformat happy @@ -4863,11 +4867,17 @@

    self._md_file.new_hr() self._md_file.new_header(level=2, title=f'Implementation for part {part_label}') wrote_label_content = False + # To reduce verbosity by default, the main component + # is conditionally written for each part dependant on the control context. + if context.purpose == ContextPurpose.SSP and context.include_all_parts: + self._process_main_component(prt.id, part_label, comp_dict) + wrote_label_content = True sorted_comp_names = sorted(comp_dict.keys()) for comp_name in sorted_comp_names: - dic = comp_dict[comp_name] + # This System already handled if comp_name == const.SSP_MAIN_COMP_NAME: continue + dic = comp_dict[comp_name] if part_label in dic: # insert the component name for ssp but not for comp_def # because there should only be one component in generated comp_def markdown @@ -4895,6 +4905,24 @@

    self._insert_comp_info(part_label, dic, context) self._md_file.new_hr() + def _skip_part(self, context: ControlContext, part_label: str, comp_dict: CompDict) -> bool: + """ + Check if a part should be skipped based on rules and context. + + Notes: The default logic is to conditionally add control parts based + on whether the component has rules associated with that part. This can be + changed using the control context for SSP markdown. + """ + if context.purpose == ContextPurpose.SSP and context.include_all_parts: + return False + else: + no_applied_rules = True + for _, dic in comp_dict.items(): + if part_label in dic and dic[part_label].rules: + no_applied_rules = False + break + return no_applied_rules + def _dump_subpart_infos(self, level: int, part: Dict[str, Any]) -> None: name = part['name'] title = self._sections_dict.get(name, name) if self._sections_dict else name diff --git a/api_reference/trestle.core.repository/index.html b/api_reference/trestle.core.repository/index.html index 3a64fe521..e65c80177 100644 --- a/api_reference/trestle.core.repository/index.html +++ b/api_reference/trestle.core.repository/index.html @@ -5090,7 +5090,7 @@

    markdown_dir: str, set_parameters: bool = False, regenerate: bool = False, - version: str = '' + version: Optional[str] = None ) -> bool: """Assemble catalog markdown into OSCAL Catalog in JSON.""" logger.debug(f'Assembling model {name} of type catalog.') @@ -5125,10 +5125,10 @@

    markdown_dir: str, set_parameters: bool = False, regenerate: bool = False, - version: str = '', - sections: str = '', - required_sections: str = '', - allowed_sections: str = '' + version: Optional[str] = None, + sections: Optional[str] = None, + required_sections: Optional[str] = None, + allowed_sections: Optional[str] = None ) -> bool: """Assemble profile markdown into OSCAL Profile in JSON.""" logger.debug(f'Assembling model {name} of type profile.') @@ -5194,7 +5194,7 @@

    markdown_dir: str, compdefs: str, regenerate: bool = False, - version: str = '' + version: Optional[str] = None ) -> bool: """Assemble ssp markdown into OSCAL SSP in JSON.""" logger.debug(f'Assembling model {name} of type ssp.') @@ -5227,7 +5227,7 @@

    name: str, output: str, force_overwrite: bool = False, - yaml_header: str = '', + yaml_header: Optional[str] = None, overwrite_header_values: bool = False ) -> bool: """Generate catalog markdown from OSCAL Catalog in JSON.""" @@ -5260,10 +5260,10 @@

    name: str, output: str, force_overwrite: bool = False, - yaml_header: str = '', + yaml_header: Optional[str] = None, overwrite_header_values: bool = False, - sections: str = '', - required_sections: str = '' + sections: Optional[str] = None, + required_sections: Optional[str] = None ) -> bool: """Generate profile markdown from OSCAL Profile in JSON.""" logger.debug(f'Generating markdown for {name} of type profile.') @@ -5322,9 +5322,10 @@

    profile: str, output: str, compdefs: str, - leveraged_ssp: str = '', + leveraged_ssp: Optional[str] = None, force_overwrite: bool = False, - yaml_header: str = '', + include_all_parts: bool = False, + yaml_header: Optional[str] = None, overwrite_header_values: bool = False ) -> bool: """Generate ssp markdown from OSCAL Profile and Component Definitions.""" @@ -5339,6 +5340,7 @@

    leveraged_ssp=leveraged_ssp, trestle_root=self.root_dir, force_overwrite=force_overwrite, + include_all_parts=include_all_parts, yaml_header=yaml_header, overwrite_header_values=overwrite_header_values, verbose=verbose @@ -5402,7 +5404,7 @@

    -assemble_catalog_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version='') +assemble_catalog_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version=None) ¤
    @@ -5420,7 +5422,7 @@
    markdown_dir: str, set_parameters: bool = False, regenerate: bool = False, - version: str = '' + version: Optional[str] = None ) -> bool: """Assemble catalog markdown into OSCAL Catalog in JSON.""" logger.debug(f'Assembling model {name} of type catalog.') @@ -5511,7 +5513,7 @@
    -assemble_profile_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version='', sections='', required_sections='', allowed_sections='') +assemble_profile_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version=None, sections=None, required_sections=None, allowed_sections=None) ¤
    @@ -5529,10 +5531,10 @@
    markdown_dir: str, set_parameters: bool = False, regenerate: bool = False, - version: str = '', - sections: str = '', - required_sections: str = '', - allowed_sections: str = '' + version: Optional[str] = None, + sections: Optional[str] = None, + required_sections: Optional[str] = None, + allowed_sections: Optional[str] = None ) -> bool: """Assemble profile markdown into OSCAL Profile in JSON.""" logger.debug(f'Assembling model {name} of type profile.') @@ -5575,7 +5577,7 @@
    -assemble_ssp_markdown(self, name, output, markdown_dir, compdefs, regenerate=False, version='') +assemble_ssp_markdown(self, name, output, markdown_dir, compdefs, regenerate=False, version=None) ¤
    @@ -5593,7 +5595,7 @@
    markdown_dir: str, compdefs: str, regenerate: bool = False, - version: str = '' + version: Optional[str] = None ) -> bool: """Assemble ssp markdown into OSCAL SSP in JSON.""" logger.debug(f'Assembling model {name} of type ssp.') @@ -5633,7 +5635,7 @@
    -generate_catalog_markdown(self, name, output, force_overwrite=False, yaml_header='', overwrite_header_values=False) +generate_catalog_markdown(self, name, output, force_overwrite=False, yaml_header=None, overwrite_header_values=False) ¤
    @@ -5649,7 +5651,7 @@
    name: str, output: str, force_overwrite: bool = False, - yaml_header: str = '', + yaml_header: Optional[str] = None, overwrite_header_values: bool = False ) -> bool: """Generate catalog markdown from OSCAL Catalog in JSON.""" @@ -5737,7 +5739,7 @@
    -generate_profile_markdown(self, name, output, force_overwrite=False, yaml_header='', overwrite_header_values=False, sections='', required_sections='') +generate_profile_markdown(self, name, output, force_overwrite=False, yaml_header=None, overwrite_header_values=False, sections=None, required_sections=None) ¤
    @@ -5753,10 +5755,10 @@
    name: str, output: str, force_overwrite: bool = False, - yaml_header: str = '', + yaml_header: Optional[str] = None, overwrite_header_values: bool = False, - sections: str = '', - required_sections: str = '' + sections: Optional[str] = None, + required_sections: Optional[str] = None ) -> bool: """Generate profile markdown from OSCAL Profile in JSON.""" logger.debug(f'Generating markdown for {name} of type profile.') @@ -5797,7 +5799,7 @@
    -generate_ssp_markdown(self, profile, output, compdefs, leveraged_ssp='', force_overwrite=False, yaml_header='', overwrite_header_values=False) +generate_ssp_markdown(self, profile, output, compdefs, leveraged_ssp=None, force_overwrite=False, include_all_parts=False, yaml_header=None, overwrite_header_values=False) ¤
    @@ -5813,9 +5815,10 @@
    profile: str, output: str, compdefs: str, - leveraged_ssp: str = '', + leveraged_ssp: Optional[str] = None, force_overwrite: bool = False, - yaml_header: str = '', + include_all_parts: bool = False, + yaml_header: Optional[str] = None, overwrite_header_values: bool = False ) -> bool: """Generate ssp markdown from OSCAL Profile and Component Definitions.""" @@ -5830,6 +5833,7 @@
    leveraged_ssp=leveraged_ssp, trestle_root=self.root_dir, force_overwrite=force_overwrite, + include_all_parts=include_all_parts, yaml_header=yaml_header, overwrite_header_values=overwrite_header_values, verbose=verbose diff --git a/api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/index.html b/api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/index.html index e20e7a90d..eb379bf44 100644 --- a/api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/index.html +++ b/api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/index.html @@ -5436,19 +5436,27 @@

    def _add_property(self, xlsx_helper: XlsxHelper, props: List[Property], row: int, key: str) -> None: """Add property.""" - name = self._get_normalized_name(key) - value = xlsx_helper.get(row, key) - if value: - props.append(self._create_property(name, value)) + try: + name = self._get_normalized_name(key) + value = xlsx_helper.get(row, key) + if value: + props.append(self._create_property(name, value)) + except KeyError as e: + text = f'key {e} not found.' + logger.debug(text) def _add_property_boolean(self, xlsx_helper: XlsxHelper, props: List[Property], row: int, key: str) -> None: """Add property.""" - name = self._get_normalized_name(key) - value = xlsx_helper.get(row, key) - if value: - props.append(self._create_property(name, 'True')) - else: - props.append(self._create_property(name, 'False')) + try: + name = self._get_normalized_name(key) + value = xlsx_helper.get(row, key) + if value: + props.append(self._create_property(name, 'True')) + else: + props.append(self._create_property(name, 'False')) + except KeyError as e: + text = f'key {e} not found.' + logger.debug(text) def _add_part(self, xlsx_helper: XlsxHelper, parts: List[Part], id_: str, row: int, key: str) -> None: """Add part.""" @@ -5862,7 +5870,7 @@

    def _mapper(self) -> None: """Map columns heading names to column numbers.""" self._col_name_to_number = {} - cols = self._work_sheet.max_column + cols = self._work_sheet.max_column + 1 row = 1 for col in range(row, cols): cell = self._work_sheet.cell(row, col) diff --git a/contributing/mkdocs_contributing/index.html b/contributing/mkdocs_contributing/index.html index 08e904254..45321e5df 100644 --- a/contributing/mkdocs_contributing/index.html +++ b/contributing/mkdocs_contributing/index.html @@ -4754,7 +4754,6 @@

    Contributing In GeneralNote: We appreciate your effort, and want to avoid a situation where a contribution requires extensive rework (by you or by us), sits in backlog for a long time, or cannot be accepted at all!

    -

    We have also adopted Contributor Covenant Code of Conduct.

    Proposing new features¤

    If you would like to implement a new feature, please raise an issue labelled enhancement before sending a pull request so the feature can be discussed. This is to avoid diff --git a/maintainers/index.html b/maintainers/index.html index bc8fc56d9..5b42f1752 100644 --- a/maintainers/index.html +++ b/maintainers/index.html @@ -4421,7 +4421,6 @@

    Maintainers

    Alejandro Jose Leiva Palomo AleJo2995

    Christopher Butler butler54

    Lou Degenaro degenaro

    -

    Frank Suits fsuits

    Jennifer Power jpower432

    Manjiree Gadgil mrgadgil

    Vikas Agarwal vikas-agarwal76

    diff --git a/mkdocs_code_of_conduct/index.html b/mkdocs_code_of_conduct/index.html index bce349a88..a997bf728 100644 --- a/mkdocs_code_of_conduct/index.html +++ b/mkdocs_code_of_conduct/index.html @@ -4425,8 +4425,7 @@

    Code of Conduct¤

    -

    The code of conduct now resides at the organization level in the community repository. Please visit https://github.com/oscal-compass/community/blob/main/CODE_OF_CONDUCT.md to review the common code of conduct.

    -

    Note: The code of conduct is subject to change as compliance-trestle is on-boarded as a CNFC sandbox project.

    +

    Please refer to our OSCAL Compass Community Code of Conduct.

    diff --git a/objects.inv b/objects.inv index 90501f0330fd0abd4a5a85dd722716eb578a0f5f..fa7e98b73b2d6e1b88a3bd5ca9e6ac0193cb9f9f 100644 GIT binary patch delta 32946 zcmV)-K!?A$h62!r0+65wwad2LlAKwwrz`<~Kgg87d=Yw!-EvE&c)eO|gS*Ai6x$fuH^^#olW_?8}3i$F`GT44yZ%Boy52)0mZzc5^l6v&5{3c4ml_)U?P2$#n zZnw*=>QL)X|6E?~R^OJQlF{jZy8j}|_Z?x2FBg|zm%-xGR#rhW(d+egDV*$v@^Te& zck5euY{j{|r}G=BE9%wfU~_-Hl*Y4J+(^VW*e$+*Af(D=Uii9PT+ta$rMkMgD=Xw; zC)|=+y}3v*tzU0eUskt}rjv%KN^~oK4s+>8w8!IW@u$dAf^tQ6)m*K%ch^Gpc5$<$ z*8H~Ie3AuZeZRZAC#xS#NJf=88&J z#M0}lt>_LrIz{pAuf&zM3+^_{&#OOz>*ej2-B(im}GO*S_1VDTAdJUjA`;eSftCwEW9b3}R)<+AO#0>u+M@b-CCruGeIz@yop!Y+bKz z>Eb|Hd6iF#fgGLc^<7YnKDW~J#MqNmT%J4;Fla?TuZfGWQeEAa{Y@MXm5yoKe7zL@ zvG}s2J$E;Y&F@$1@3*9erh~uqd$h1;kiNv!1b-&u6dNfFMS4MnV zS#b`xgeg;L{<*lhR`XzFs_Xj=bq@S09G^^Ux4YX?n)2%E4>^ZOCf6Da1$XNeUECYe zR@0Q5+r>2qB8MCITc|kkKxUY+S<31RV~P5v3mxTj#_IO#QdIrL?d39m__kVpr<{M$ z+M?n2_jDO%bt@A7=lg3p*KmDDuX??vi}#Hx>HMCO{j&acwZ7caAB9So{6JK~^vB|Q zeYpVihfIKzTXhfP~I$mc9&n(fNlB5EkO3R(dCL*of3d`MIt~bkId$+h;5@Xk5 zbT6GTSOj<1i(7>5X1Tq;-q9-)&vY2VOeKuCX0$ec`DLSZ>nmsX=N)m& zr6T02(ZYypMoB}im{J*Wy(ne+t3}DuUn`|7;!07<13ogGdHo^Li^xln0S?|6sHxLSD(cb!YNhlSpH=+!S;r7=* z@4hZ?>27nH+N$f(DL2cog3J5uZha%q-}?6R>dXBGj1e{I+v*Afsi)Zy;_J4U3*e>N#6}hf_v$~@^D2+JX z3}2(EZsrGzYjq<}mX<9kLoXJfTu^H0>IIa9$~#)~Ax<1xE?8V$_0~27pVyoE;hY`e zq-_NS9(PTkU05Pi@0Oe0pX6s$)oWudEaIB4D3sIs`ZhG3oEQ;_07#cs8^u8V=Ii>J z@P4^k;&)$vddvELb4l3j?VSjDt52)zmFRBJj?rP!b`LEru0&BomMC4i4!B;E6*=SC z3R1Hwb-yn*w}fkh)!I))=b~Lxx?RW>Dyol)i(*43yIXBPuUaLT_)(rA1mJjA3kWGY zT(f?VRQ2=jj&kAKcD>nA_O$Jt%0!*zSExkv22QSjKJdkA`lbh9`Q!vOWcPKotwwqt zPoAC(BfUblat-$CR?Ul&F2YvISHag!c~kF}TDWuE|4T%0(jr${ zwKDa8%$?S~UGIX$-QD%-Qa%z$EG~!J>XKVfcRe+uPOK>>dsgHv)vDKj0y~Gi5qXPJ z1z(JJ8zE0!>xd^dw5nP;C}RJ&<@NdwP@zlxo5erXO^qu#$xS+$UOx4^{#*?QC~p}F z%M$%%x2&EkqMc(iQ{iG8{J#7Xp-kHqcdH$LT|wP#7PngwfN#|DhAo|}h<1AVSk8`; z4iPKya>EY7bsn{_x*-Qtrkts-q(%7HA)2fnmt0*2x8$AU%k}!x;u_I2)hCh^L_ zTKDQ+jXrmzC$W^iUfupqueu@Jv!W5bC%g~#efeoCw`ZWda=))`uh!qU!PQ2tHY*>d zqP>#ag!|13BQJ+3DoGRGfl?bEG>`Lt5#M|=)oas3Fxty5P>4H>vYHKVEir2L-}A$h zbHNBwGsjFP&+>fwR>0zi$3&_v(3g3h;BC%hEC{C}PAuLF(0t|{$;q#Bu+`l^v;B`ClY8F>Q7rp>mdE9* z4W=HD=`i-I$isaR9P{iiK?)9XxBcK47SC9o{)w8Ki*AM?KCwdduCx&3lQ^R4U*tyd z7+RcimW!_^XyS5FG!Tf_o#QosNW%jQ!X(LlvIvHIj-!aBF!>~t9bVRemzc*7z~jbW z4@sQ0IT*?i_5$%{}HuD#WNC1E8lzFeW+ zZY2L2M!|`zBqSUw$Tkd(nd>6<7@iU!z{fEYHlF2?Dp~yWfaCm?i9q^;y;hgHDk~hr zIc*e+ z&{Pg}td0`_({?yKh52N2Ql7>{F1AOuk00Z`dSBjW6@4bp{#fcdOaR#u9_ueKUw@Z} zdq#3BloIi`FEy)fFk4Pda-4GUxgvOB`9sEIG5Sd4p|$I{;|N)Qrk;}QK@8I6RUfBM zr9P(wh+j+9vgn5S6N!9z8Cwo%j1RphYFP(ul-27m@2i$i>dS8O7t*a|HaN;xFEXp^ z(2@8Uvn1j&SqH+;<$ufrGmV1NDUPHv_k$BwaAG`oc&*(F%9O<*Op?;PxEEaGlfk3N zGUa@v_~vDQ_0|G^k)$8%$z3?Io`NZV#veD!^!N3Gadh}1_F&z9Ha#8w%=yXity$qe6%Z0c^Rd*6$OdRo09t9s%nUSMdp6Q2E zQQo$|1IvGtCCX1_>Oj48CtoD_rDSd>{}jc!A1)Vv>5v8N?^7(U7m<76)H)ZL zQ?gKE&eZL3SrcSp!FN|4zQ|K~)EV55$COi_L8}bWLFGah%iv#shFDEDq`q%(qm1p^R>}cie3lM}6>w z?}Q2Ds5QMo`Hbizbd)03a?=W-`tfn0=GlwQV*AzR!7giIoA++miQB%_<2`jXjF7*x z?uPFv%W;CpAaaV&c0&3+>74DemvX{~ShC84)UvjJ%QxQB<%MPWog_&8?MqSW?=H$r zmd8(VDw|8*w;FY|>;xwdP%bZI&`~MHQ3s_|Clr>WJj)>6eC8cV%lY%^y6PT&nzGz_ z$)_Eo?1C8mn9J2b2~)CxnlmT-HaWYHbH(~@Wj5`}i0+5p6BQ$lP7=BMUAI&G;l$(B~S!k~1TJ=xj&o@bsFQHqazIf|bD@Dzwudv=uYGcgSfKB|p>dutaq9J39W$4P&K;<{+8uqOFlq?ESNOke4L zKmk#aa6o3uGNV15$LGf^je4 zpLtxMufn?0#3?VrbWhI9vxk#>^g)z0xy+?LnxVxr=kMY6Vqh&7wCZ02p)++9Kk(6M z0IPAmJLR(c{o-ylG5ArS?3P|rLCZ&fSoA-7CClm+gi#dBekd+H_4InGAE-J+{@YUh zTiJjx{}E+BQ?Jd?Yee*O{9e(j?A3=rq)9&qAQs;=f7FjKxRj1szy>y}jJOf?pyyRwB)lz^*yE!(yXUEI~|+logb=I<`qcAYgyH#}81G=4B#KqjGl4&)%pHa%@C|llxkU%RYU~K1y5U!&Yh~^O+m8 zPgt0jO{yOgKYMfPgLCfY=zSCn(?5S>Qdbjc?U$9ZxBZxs8#LM#6M8WT1!ViNSoqFJ@3JbusHD#)vgcLnh#gB z>)D)K?FP%)hicRZ>Ex%hkXsDYfk5WF4|EC#n)gA{O2p*mfATKI$GReaA5Trb`zYP4 znk(cVr!69~NPGS`nSqxJ7(T)w;#pp>sCCh)qxKP+CTy6=MOHx)KFDS2j{*A?^MZe< zwkgYrtyX7wYuCAtRL+ix`1ONadDU%L{gXcDfz<8z-1TN?`RU1+S+_xLS^6m7)L+oy zmg6ku?D_I}bdrS@Bu$uq*_|i1K`yFr@5|+h@RPma>P61l$HWEu(>DJfp}T{Zm!qU(C1YOk`^?7zOR;+vqyQCDbpKg&ggjb zjcYon{}#;+Cp7f)b(gvY&D>ZWS;8ba^H~{cmCf5AX16S@mIyeNPWkD{n2Y5fm)G}K z%i!zs`p&gub@U zw;nH}ZVP;pFYhBmz(A7<+8qiZawv7^&QVskxR7Cl3WtcQj<&c zd5ZFOw>TSnx7hx!%)sOI+b}&|!S&(Y{du?47t}e(XYhoP26#N-!wopc+1D4>c{)G? z_jc;_dzi#8>-!BpfkoNgc~VP$b|PZdT>u--mHs{s^S8E`856bEsDd4iiJbBD$gK7` z4h7nOd5YDV%2^@zx~jhKlYFsN%A%m|s6HA|^y}&!G@F^JY{8cP7bY>W*(;um1UDm#TXc{E?s4V-?Pqt^W9Q(5%bWp7yo*dJdPZ zGjGOa>&_&(Y~Atdvh|N8yIS3w;E()Qoc|PvE$_ZS!ww06~Ymy{usoMuddy67WZ&UiufoOokyPe@})b$_5IE>HkbRb z(g}-C1fqoBl1(i$mCn@7Gl$^sXw^)3EX3nB|4Xc5E2Wk{6Gc zmj?PhDf*!_z`_!YETxZPsZqfzWzJc>-=ri+0B|&9nfvt>A(BdI*JY*#(zWW zO}O<>@!&BN!>W+~aJ|6J^d011@uK>{|E}Lc{{)Mg8)`G2G&{qWsP?d^e(b+d({+HY zf4ZFIm+wG0?d7Yr{~LXkax<8IXY&6Q^lt*EWeetqr$XF}!il7x2bJ&rw5|7lb9we# zMNyFNk`s4XuVKT?(u@5e3Qk3wxOEs)zy_vYo>N}+)8C;=!){(lEq4JbvMhMY!}OGd z-dl1EbIyYOa~P-RL9?XXw>He5&fWm-y9NB1h^tz6fyX#yz8g?v`t|5)5~mu9;9HP0 zVX^WxLlJYn>`e_z_a(#2NxV`!y zt+`rX-rp>5ciU=}t6c8+F`Blzy%ndYM!9 z@E6IW9fGnbkT^HeFx}@mYvicL4dJ z_e9-J{3PYC;(rb&+eX{v1Y7BgVO{!E-J1>SvtV<2-{Wa*>$9srH$mF%99!tG)UOWb z+J)hA&ZltF*nZnE`JwlJL>-U*6y=rppUY9V&~`f7@93)+W>_C<^{IDd-H!G|?II8N z3?r@HNaAoVE#+NKr!As6y*6dimU3kIW0oJ(tvK~hoE|CP1Qmyg&UWn;-8Nl!M8^T` z*1ZY&cje!&)n9)z4v0;sMYqSLm&4oiR%f#5wGIu<*&%ze@3!TC$KDrq>y(q#H|iIM z+GtO3={OD)<9yhh`6;Ah67O9~RQ<_G@~&sxim|DF=XC0wQEq*}9asOg>lDHyxVleb z-7D0m-j#Lh4HLCpGS@`uMG}X6C-i^VF938vTm*q4h?1T2@^1efa=f8)b~bYSqILonp!nfb zFkfK4e`bd;*oWd*U�=4do&&U%VtMd>u~D9Ve83VB7;qu2L&l>f<{_QJ}t;bsBM@ zl}l>tqX_58=c@waV8VeZW1@6RVzpo#K-|jzJ7i@`d6#^DY>Rk|)2QkZL6ONNrSTDc z-0CT%CM!c}BDaU4{_@jRY_n!yt88XUvoxmhtsORm?j+l+JM zhu#x)8|6$=-iiM?T(~ycE?4b)`p)yAQ|7GZ&3IZ7swp~$Q{c*RIUSQ&#zO>FXQcex z1Zl_fFf~Gw}vUy-U7)x%4lK376K#-WR^OEPuT_S$|$#FFnz=+dCvl{Q0u!gs{%hV8l2m$$qjZ;H*h7 z_-}WyPvYP;JS0K6ZILgke$A9;oLXQWBrz|%g5$k^SDsBtCg9a?4UDcaANeTr9D2=Ig|K z9baQ74L`KQu@LfHT(8{Umuv!-2U^blKE=6z56wkF8F4HrA~$+hWzz&fY#Z&I25J$dSaFSC3@~g`?PS$h$bwxRqnHDIVmDQ9Yg9xVm6b9rt@5uFLbZqc{^*UIN~K zt56L;SBH}o@C;a4Z`Gu}+J!GZ90l|5^S9$XoxYqJlDl7hl*_Q09Xo3?bTvK;xvq(4 zJpl3<-m?^?GbXbNf6~YP9Qia(Ig^LJEKKqzv!He3%zs<-A&Jiu*kd02jEmaUz@?u8RDSu zy!r^J-}vUsCC`DngY$z0>HZAk(Nh}#eTpAn4gbfs;I6t$wkb;sY|_aDT`acS)t6hj zMPBfEy}3b7UbeW`i%-kzb0F87;PUHwrC+`52fSQ-TLw4l`|WOV`E}`y`)zT5eZQ1n zczJWT`!m??Hmln&{^@5s?sW^wZywyPZ_x+8fZxlhAQ$%Q#2i5mi=|vi=-W~ziTgQv z{LoBg!C^jb2N^IQw}A|tkJ~>rPJ|B?^%1zdxx-^|o4owgyRuFrzV_h!@W>KJ*0Uo@y zfJ?ee`Yxl4cads|s`a&Ae(GIWr)zzxwmwSV>n~t&tvfNC9mS1SE*`FaL{9q4E5Pa* z<@fOU;o{*{t?IX595wLSi3q!1F@y8zwOOQLyIz7AYu|UM8z7B}{Zd+wUJhzpIK?-=DwT)TVq;?eTyj8HJ;U0?f&{pn59ox?Kx zbw4;o-2BoOOC_C9tL6ZHi`h>!&bGAK6PD^vb_sVj$f+sq9u_fwjL&&UEGJVTEwC?m^lh+zoOY#c!;P-D)_Dxp zhI5~lPHRR|TJ8om^`x_cpQ}`OIzKb@i9qR^Ibe-3I7qscS>+C^NUwdm^7LsvB}=Or3c; zD?RpE&Pl%&`d#OLALf*NlrFL{=QCf=(NWqhIB$39wB@68nohGmNY~lrjGd#yNbY&N ziE6<|=^Uyt-nxX$yyguDp=>k9Gw|{0AnWOsd9>~J&PZU3yOl*}Cnh^}cj`7&9lrg; z=WJ2g>svqPHoZBmVNtf{f!m^pfsalDSoL{#%9Z##m&Fo)gv9of%XK9ar)KJzq;8CU zen2iLI!6=Qi#z1=O08|h2%D3KKZ7`%+?UHA9~ZLgv+t^1iClH82k}|%>BCNYpJe-jz&A)I{em#w zyc%Wl#X9hR*@=jYtNJgk&krs2qI~l}tbc6s5uMfwy`5N=Prh5(eBw>Hi`|!LHE^n) zOd0tZoF z0nwAH9sh#rlvHm$c|4`%rV0>@Iz)0!o%~|-xR^tKwOM*P7@ZfR|6UKqP=~rPEs2MZ zOd1Y9Jy43r`yk`{FtKu)>O=2|UaW5Ju9xyb*yUBQS^n4kYNP(NwYV53v#h;nvhtVm zPsRe!iK$~Q#_0v06i~;Pd=j87Ui3*ob9>n*0oXgx?WLat;5je;q`mD}pDe$7?a@kL>;pC zVNjRvdGOQ2dmZw0=-vi8U9OkmO&1Cu)O3L7=uzbcFVL9L;^Cug3#T59^+r3xB99hd zzUdg8-0D5opvk3zc#JJ3(rach!0^CguzaQ!1M3;*Gp86>{~^VM`%Wk=w%>SSp#5bN z6Y3|Jm_&RkF=*bqkgo~VhUjO19<$-0r!E^3dbYA5c}R5z%io-2Lv40r#Af9h2%h_E zK(y0+f5quv;nb~N)DMq|SZ%NJw$jbjWx~RARfd6y$<;>kB96qNj77@Gr=2q^@gjWU z09o680IkHuxRNs}?T@fCRM5nISBR_AAGTljQG^x*6qfC0bw&fNZt+bb0Ta^67 zb>!*JUPqYv6n5kZ&*QHAtAEO~ktDPMe?OO(yVbXk)1vKeu~YBx_%JQHzr9+1UfnLQ z&eJ0Kw%f~QU~z_$X|&+%)@HUve2jU>bn2Co^9Hzm2|J+M&~`RezM*r@c#^yU?%j{R zDP$AoBu$%_h5=1D^Qj`qzIH9Cf6(F$;e#KZ3UR9nPNb^mPk$#k8PB~V%_b*VWEeF! zRm&H{7VL0LES?#qYfbffRdG0Y;WQyMy9woca_fIq2c*0UfNzWNZC7JIqAS}JrPLZ>h2m-V;hMg-j8YJC}OmS2{C_>(9nH-De2 z+kY;CD>0ZAU-#xN_`KfSEWCZ|>(zGW_3Li$KW%rb-TiL0zV&-SmD6KqKyLrM`Lw>q zGmm+;XPi%8NcV<>9dKsAbfs2_ftve?0_?io-4IF z__hmM zjf(;`L*Q`HR-c?C?|6yYF>bED*WbnJI&{O#xY!(lVH5?g;URI3502dZNq;W_7AD8N zQQ5DU7yfW^%}f%f%rDVt4Z15ZWj}p)9fkCZlPA$Lko!G{a!;tIJUl*or+PoOYPFp= zqTI_gPUUlsj?Xy|fO)}=0gwOX?^~Dm2(lA#Czg-J@r!U@zh84wzG!{wU0J(aVX3{? zTf8C7O&e_%o8`@V^3uM!7(ZX>{!ZRffn&aJ zRw&A4&csOkE-ap*j?l%x%k}_JT(ur~V8iI~)FUS9FXaP7#WVLx)_)(6)2j0E8?^M^Qe}WHyj)D(Q}H2b5EzV$b!GP#R{T1Ab+{=0}hfyF0=JGlRI|2z z*gl-E0@c+q4G+v8^)b%5$1nMKN)o>`)m<#NKAH`d{nZ~WdpHC?^YC~SKI_F>YqDJ1 zn|l1FO?2{F1b;jpRS}sEr=*BwhxJ1|gg;miKJYBDAA-+8<}3-V_Me-D6yZtvhrfO! zi0TDjUWraCF5btfL$@z?WoRyj=~EoN&s(4_&tUU zPA};s;yS*mlZI~bx=tFP+dDgH*ymuny}gr$J?9mkL@jWCk0(_FTwmr%!*_Y3ClT59 zwVp&+n|FKCAkWjc_F)kw+0<8Tkq|9kDoVjTX5qmjEze{o@%a6Cc=QR&J;J!hZzf{s zWBlYXuYZ-m3w8fQ_}uX%N6T3%x4u_STh9~v{Ql+h)847|9%|yqi=toMGb3%oF$t}o zP*R_HN7Ch<{UqHx@qfGiI9b;1-i3|4)9nfyfXf|<>H6{^?66({1V(TeW1p}vhf~~E z_e|GU_wK>p!EwpZ7@&OlMj%R(2z9Sht4{kt!k$O7xIH%; zBo{LHf#vKe=EAS^8(PSq>RqIh_xLD(dQ`^B)!x%8-;x@|<(HlI7Ss1M)tFqrd5uO< z-a(M}6U$e9R_SZ5c6?;@^Yl|ri~jjHq%Q6Z%?Ve$jij8BoxZt>gL1Xq*VJBbg|Mwo zR)6Az4KK%t;*&f}UMw!z&gUjb+g-*E`gi4DY>clmrQ^&eshX|-F$$`m)>9gjPZGEt z>fKRs`po14W%aK|PS`f_Nrx9Yw?Fl+?8Qd>(RTZ@Sq#UQEl*$`vO@e`&SXwMSj}hN zk+izjY;-@%jU`zw-z7Qu@H?qn7f@G@T7T5S_hI4qldwIA_hM9*eEMq4dI3jCYa@R5R5j_qjQH#230L4>g%^+N&tn8XE?P~HEALewUn)PzmT?+JTqBMj@O z2BI$DYK8y^66&nLW90A%&4@+$&+!{&9JIf3=*N$1NfH?d4F&>I$U0Ti#SH4{jEB7|QM927h#10+L1XOOW$fewTC1PpQ45sZYHt>voPOYTs22w>iN!+U{r9isE`| zMF#2yo{fq&VZdJ^JB{L5Ya57xKUk!`T=O3>CgE&{MYWy*|w9ZCBR1*5}-wp!Va|@13;S^k5!IeBhX+ocW>gLJZ|>cKUL| zJ+er2>|>41^7tuELz`vlG+_0@9`1)J2IS@T1?A&0@=%|^Xx({YIe#G}zAoc-Zz!^d z%B{>Sm#(=%^dnWX0M(7~hmf1o7ZXZo|C5vCWxgyS?^jk=#IF1+xpt?fO(?ijIH#xg zDdCQf@Dnz{;yHdos@uc-gbg?w*zK`?!UoKFwx6;Y?hp8rw!-x(f5Jw%JnB!0w|(B9 zl5O+QKOy&wovwT;Cx3hRYic5xM7AEuzcoU08>vrIv>kg}s$Q@>&+_2FCnq{vfZG7s zmSTHrdXm2FgOR-tP7xo*S#%#Om>Nch`O~T1A%5DEWAD(^;&pX#=utlv{?1_= z{M-cTi$(qCY0sY%fouaXA=W3`6U;g+xgPO+Af?+|F| z@Rm`Q5Nr`*38@p~D;@DH-OBi9`P&KGNCC+Fq@Kk0$Cmq21P6g)xi_X>1~p|1CMu+Q zxW!mY?C$`JTpOxf=nI&$mzc@7X6OlZe_yo-`45jYmLIrURwuq_`T+baP=6_X0PZ`d4>iGWQXg!A&#XSs z0AFc+2<;=U4{_0neSmqU4kq_*dlA29+#}Rtt64f|oW6*E%<|VDF4(~*x!fHreqm+Y zDrahaHXvv6aX6pE6KAfQv9w?|6Mr1roEHzwCi)}!OJy_H1I*|8 z&0n+b_|K;LN?I=W^ykCSnab&|{Y=`xy*~_YCnswbX>{3|ssVXXALh-NhS45fYOn!d z%Nk_*^RGetnXvwxZ4mF<=7t;L*Yif&;L`vHo8Ze0hv7b~ahQzu$wBJbx?25iSZ_q+ zP*ME-DSs)r%Nij4(P;qV4##!o@?B=oW@mw!Y=ST_uLX{2U>lYs1`7Fq1wf70g7t#)5g+^Yu6JOYU@6Vh+?f8@NI@O~#EW_p5??Ie;j&Hk zA1hmYKY_A^^d2Q!^z%@?$Hx}^Ou@0;hOH|YM2zJ~kt_y+6G-W#SLXRmo@=u8pg`#e5YV^R-9mPVdPNu2)RzF2bCr6_oK z^~9@RknDk#vm}%+Wp;cb+L7t_kc<;eq<_6~yIl{gA}-1eQa!MIOs8p-r=Yx2Gs26b zH<0JBY+}8~WdrUdFdIDIk=a0>0qHw78|d={XR`t4h|Vp(|L|@Pr@R6h~g zAfBaLJqu}XFi+X2=6SMqf_+=&0X}!rzj*DTUKXWmmZzJ8HEs55 z$lSOw_x2sVEP~f8FN@$c%f}*kjY3Q#?!zL~zBXwWQ~mRANL^eul2h6_UD0h=W~c8u z0<)sn47RL<9miEx45YT>Xn)CyF>7FCN18DPvIIE~cdR&0BO5z{^&rMh-fFyJC5=7D z_WNX6h+C!(3+1OgI~@VKmU~xOC?CT-JOEm35fdy_?GnKh;j$~xE8@Jn(MNiBO`-Pg zS{UfvH3O*)^zNDg_wI%S_HF|N_3oMj^X`TK@$N>R+`DUO>^Uy$9)CcW-nO+esa0uB zn@KSXS#rN_bPI&6#T=G}tj&ang)Diz_#*QlwH_>5)at-sQ89>PMJ0<16%_%ej0+SM z0Ual54mM0Q7-W>FD5xM&>my=BElwRGDq-ZAr4A5Ul{`L_y3}L-Qk622l#0ZGq!gu& zBeiNlFG?FlN>SnEhl<;XT1Yz!e- zVr)S{#Sr&p!#3j7F=WP4;K}O7t>T%o+2K&GGMaYFS^fC9(8XeJ^U{Nfa*pMEy0~*S zpNz07=95)jYx!gVOxU%OPX^2@bM2Py^K$WxK;7#@_+V4e7d$>4WFzFJgGvK z5ldQ)q9$rujZ7wL+AZjtuIl>wfT;xj$_sWN7L|TOENOFpd!nS}uy2a$OI*B?3j&iu zB@fLC8bY2Hv@S9)XarCinHe+!pBgFTTz04cnDkJo)8_}R3_ZQ}&xuUe zCJz%zl{`);)qiT+dfRDq3jldy(Yj4$5e;Yb1d&((2i$6Ed9o^XZc(Dt$t8;N>o{fP zf~e$T$m5br1EEbWjV>&?Gzg$HEV(oYaB?v~(BxurfXSu7sIP($21OzR0Ek3}I&maw zlu`YLaZXy5g&wddYjtQ%E*az{xs*j#M%Lq!fPXK?nuD&!6$V?3OA4-JYJE(_ z)Z+97vlK?2*--o%h@l?g$U`gd_4FR8W_FUVprV$Q*J_xE(PPA@rRByE;(h~z2D1cU&sPi|yCNzX$*L$A6Hw zRV)9m|9=E2|NH+&wfTSj_78|M>@dTQGVCCe9^-n?ghjn8FwI5M5k`gl0Sqqf_hGcL zzpoF=|9zAP1Z+gmM}db113>5)VTcDDEc9`pQNsWTFnk!G5RW7J1TWpd*z)F>gvDc) zA2B)ifVY zreSCwt1w6xs~9K`)A}AxzTJaY+MYZPFztJ#CIU*tBab z+S;TmE!xt!oTO7EP#T|?43Lk^)ZkFLsUdjCP7TZp#6yN^VBT_+f%KH6Orn=O)d1m{ z%6~vXbCtn?WvhnasY9S*P^FKu{z{*ES!kbt3IUb=N&HQKoIPnsn8;Dd!(zwwq+XGX zQ-+5QgX1A{G&E4;XaM-c(Xf0l@Oh(Q`HC9`(NEeifj+`U!$W5cgM^G41_qTh8ib#| zfOt-(2dSzNFaOMOq^eGYNrH#qzYZt`R)6xK5Ln5>GGGNDUG3FVN9QIH(Dv*(OQLeK zbU4IUn(83^1*jnJB5!sPw!S1+U!pZ->&37~8r%bgYI_v`6Nqz zCjg^)ALa!DjNyG4JbVuz!I6822o2hOAS_-Fpdg`ofI}Xo`wUMVBGkVLh%-``Lmij9 z`qUx0t4|+|`vlY`Kz$ZqHn)qQj(@_%=bZh05+8jtaXi38oMvH<~ zhh>Tu1so>YENF`8pn&nAMFQo9HUkhC+5qCD&=NPTa96oxl|@J#?ZV*!0I}nK3im&5L|X}$i8PWR ze{BO`w%Wpwx@k)pWuh$zR2*fQEeO^r+bE<#c1Sp1Y=JO#*hbL1U|XNo{94-J6D|Ik z_U5~xP3{Mr{pWuW%fWo05`PDJfJPA4f31qE{Tcuh#?^ccK-c>UgRS*71zG1c1XbfJ zc|?7$w5e;m)&-u_M-j&}79%-2-24$Tl1Ak$mhCZTiT|S3- zxEG_C_+KIE>x;X>prSv7ftCFM7-``j&_|X20h9*>s{9Y2um&&$L|VWg4`%`cI82=$ z0?}9MAqs7+9w2z>29M#M(Jg7~$&;>N?5SsY{1m4!dD7*PJ$2%N*JWG~`>z&6`K}?4 z^V$8n6%wHP>P=6Zcrwsz^qXr1-pC$+Bn+*o!mj(dflZHC6KQ_wH(@Seul`5^1 zRH_C0RgjBP+fw;j;k8;iAHT3IOW2;)r^W~<<9dsSbFw$6wAS_p2#h|p?>)$7-*nxa6yjx77<{vZ{dhN_YIWaJ_A^1I1a0-Tz^*m6UQ?F+mgKx^Z5m7 zbJZw@HfW7vh#zbm2Vv3}EQEQ=US1;?I%#oTsN^Rh;e(N< zJmez=_0!M3{09yL;UZ6;0sk_Hc!Nzf=r9AzFjt}s?&1Uc9v9E@*MDUxBVTX!76g=S z-b2E2&O2bz%zyI^3zdJ~!FtA_a?v|jY({zyj?7E%vT@nz9W?FQw|8Ke(DojbKES<4 zqz!ZL&>;Pl9a$QYZp+h1qU@;!z?qSWp|u`U8D=yl1S$?Q5fcKoj1~%N5N#6B4oncJ z9=8yH>f6#MuC=B%_(T&AYYgQgKjvn~SWXdMu#r**VZuGYbTB%+gz;eo-tNVW zL48?+r+Y6WNPIQN-u@UP;i^0McE>U;a=JSmN)1)VD{Wli)&$y0twmv_S?i;8VZ~SL zgR5;tftJ@A0<5Q+0V<%CI-p`!(!?cF%i_)_V1GehDa_J{R*-aoo0iO;o>&w-ywb{& zE|x1LbC$^0^aT2CLyTOW^iEYN%8M{B$R&#t5BASt`ow6ZNw?fCB`I&vm5RhOrpsRi z%hNC+yf@cKq5@J2fJ;dxhBhjh%CNj-LZITX7#T}236@} zy{V=kZK;9a9I0Yp%&1nU_n}&v)`BWo-1#IOFqe{)Ta}lJq+{h$l6Wv%it<-pumi0o z>1OJsB(Z&ej?*Yk$@NeM+oO#qv1!-3kZfdLwBO#xYM zqYp6MMx5AoYhmP>1IEvjzJ+p zoR&spE-j4-E?OLUxXWl1kcW;+9*~hLX~Opfwv~~2X(w6@xv}&H283>^T#qUZq22Ll#K2Uy@(Iz)s<(?K9Go(}M6 zpMo1AfI{#P2@r&bFvMYa0DiiWq!B1IBaJbEF=-eHN=hRzKv)_f5$C00inp#oyhdS=p>F&_34hc%sba9`GCLfz zRQwhyj`qV23h#$)AjS{d47eY*ah@=6KWyVX`C$j@#Sgno4}RE2g8i@q1Nvcy1oFc+ z#aq|dSHGj3I~YQdE@~VkkgjbUB%tC$o1r!(U1eC)-`gJy7~P$tM~8GtcXtR<(kP>Q zba!`mOG-&M(p{3$Agv(!?Dv1(+{fyCtZ zHTRws;nm{h>=?1P^|Qk%5CeMzmv&1_yMPhh2(nnT;FzJhk+7iN^6-!xm0Tou5(1>= zOk%`cE{*`pP@c8{=A0fIl8fl0!%rtCCxbO!iHPibro>RH>&XLHj8A45^X{Z?W>~|e zICXpf6Lg&Qd-=RX+QO=Wky2vl&s6HL4c#t)DvqB;b&|j7sp(o&O+ zuty(9LhZ9NwlR&t%_gOL@AX{M@>dL*m1hAAy=YNFS*j~=RjrE&HEah#)VdV`>gGpV z^@$yd8THt z8`}q(DtGpqkav+=PU_>lT)$HZknSNeL12r*=vdRl_k*nWi>!r5VeYES$Z;zh@I}!#Rw1DA|Wk1rtTjimC__v z^-wu7z~N z;mcnMl~^$q)Tg5>0Km&w6lr0zkjmNT8n;3X=JTnoRL$S5trQy-P46F=2ni)rnVKAp zFH8*6&eR%n4h}LGp7{|!JrkiiKk5)mT{FzO3u3Frsn~d$y=V3 z#0^UV%C+Pz!A@Upn-e1Djgr%kxA&>T2L9O&22chQPeFH|D~{ zWgWTAEU{1hc-a?fQ`AdWYpU47B-SKs@hVrk4gY@rVzkYP*7r5Vbo(kJ_fzeWm&4w+ zYj^2N&;Ki%8L9%D`^;L)ifek?)jsI?SS~zI+U?2;uvtbtNwoyLWUP2_*5RP|9i0YkzhvE>xxY1wf7tM}hv{(`j zL~i3O%6&r%Vo3#7 z$*?=`YXlG2Tr4s8$3i$X5OZm~)gLA3j$qqIrSU#0v*MgZc*(qycr4zH73mVUQae2U zBP&3aRG^|7u)C)kADm!Kj_!i1BPDr|X-v)SUfmY0z>&`RvrImXAhevpqgfL#&k$R0 z(h>TOr4hHayhl4c{T3ZS5b8a(L6&w zTP4W%JmauGpf-VF2yxl0Az6;*lwp5ior4?T$7jG>jpYjS<OtH;gMq% z8w_QA>@GMe9stxzBLGb@FWRJ=B8?&Mvi&tF>0qndbp-d#SH%jxqZbcV(>x3rreF~4 zXt`7+uhwU{6qP;EC=fu&mRcpSiufjmo!(F0n&aQk`t|LgA5NqtRsKs-yNKEpvbjkc z8%#g_y?m_ z$-T^%Hx^zN)aZ=zg6$1NQZw@lk?RpKCE5o}9nue^Ou*{+X7tqHhiGCndwgfy8Cq5B zijWS}`=f3~4U=xQ|EFsu1yy{KBcaM2aW!~}YsuyNycH%43wCew_oJerZ-K43AK&fR zG3^1j9UZWYCbJXeGu(GdlNrr0*HGPt-fNcJl+BK2QmzPE(lV5fO8xgmi?6~zm%`0xlZ9wp@_yLp&XsH8$gRD^phI7#A)QDVZt1(3pl1lzM$J6u(d+tGzKvL8a1TkgP#j4%(if6!ZZ6#a zs)pH;wC_!czeY?-nhf`6-YX`y#WT8W(I54CSHy{u zfQE=&@djy&KlR#?ekRBvz}*7Tz#8D8a;in&ehUi^Nwjllb+Y zi@wVFhN5{Zpao)}L1$6@Q&HUwQ2i;!rvhkb1bxM})`NE@2e!Khw(1ae@>xz+UkF=k zjnQw@nMdSm-s{RRD{e~sW&nMryW!0Z@mFps+D21hS->Hf0y&*51$FKbQB#`XP3#d- zQkhAu!(XV)V7+CL1~fN&%QAu9;V4lC??SvsWTOnsBfNW2OBMgnGn?8&tVh;kQvr;B zRWRXQOtJs6U$rW=q1pLrQ!OYrx((;zXa6nOFO91Veeu`(RxW=o+NI?4bcux?M13p_ zt-pCka+3dEF*2GC+%lTM;u8dlTTYXa-70dEwzn#BFxjs%mqa2Affi;iWswyaA~AoZ z;=Zg_re2*W%2|UO?mrhB>YRjrCXR@(`X=chBhzf-jXFt$MxEh^E5z-H{X0InV7n0$RlJs+9<2ZCky+e&pGz#TC#63kQb7N3(f4sU+IA}ux^@4(QyinO$Z zZWMxpCnRsNbYq2ybjsr6XCr?`cE!T&C4=jdCC!M2Zu2*F}o#6oZ?Ed;CWKTI<5w3wH(s#$K3VtgEZinMqYT=jpd0<@<8q ztw`N;U%Nb8xpuA&QzoL}&H#=?_ZM{O%g1!ixl1;5Y zTQt{IK#SQT9vZw9K~^{b5G_;+F@BGMbT1Jq)6+AoiLzd!1o&0MqTy5*!B_I+WH^o{ zh{AfrNj)S~?7SzZFP3?Y3SJV^hN)9I8A^MTrp7)Gg<+*NzT-2?Q(xan;2STAl;Uor z9!}1A1S1^ngu?e>S|QG0)2Kw8tjHf!Jlls*$+$N-r6(M|Su*F#q5qMsj)5A_8^Z{M zH$qwj0&z4gX>ZavSCUlGH{vmg2V*dOnsCS%#1JkdQ6^$vv&3+A76%7l@nc0&relZw z>|k7n9UXLcl9EP<5oTKvCwg%65)DGheD+w4-B0J%S!#+1%_a{dL~pt2;~M4BpI z<7g9{;}9WS;^c(>1aV-&9zkjYHKDIkIz7K+Ms9a;_|dO$a*!S(V-W5l(E&Fgjs%HK z=+${V)?9&h*OVsBQeEB$nbZ(np73Ir6SpyXf!A}u!WJskN%(5m4d3e>* z(TkPnkN6cMw{njU;-P2{CJP4Xp>+a4zBzkcK_r=DJO^e8Gc zz_g@jw1!@p;<-!;H8!By#Wn~V+J59#lxcvp#>P;XruD5pqnb31RB!j-kKSkXX+UR6 zkdN!Yb)ylibxbfX(*DUUCcM?-cA*C44q>~1cOxI&<~+J(hV-vFF^z^c*>y)QHE}&U zLW>%{I>Tv@$hZ>xwT&?*Az^laZvYZH2PBcVd|)ScZlUodO_-Hta4`b7S-Mo6iooH+$!Wm< zLI&W>?J+q;3ZYhRhH2f6^}p`s_ENv8i;eSyChYWXadl4dZACa#DBrcRI@`>b+(W~k z=b3)KQ8S~qkrp30+`D1ibyK0HHoSc-OKDU{6BExxf8AG zIj#pz_|Y_en&0Idemi0-U`}m>nu(b$?h?O;7Gb}aGDm4dknjae?xYK?Y^xxRZ>0;t zr=0m@wXylQ+QOpOHHgvHrCalc!Yp=n#sJ@XLG+$a1rjqmeh?hgyn!c8yU1(cXZR$L zei>hXoJii^5~zE(0qAYto>0xY2EP7LORDyWxxv5?QaQZlofJi<*TjL0$CqG-3bA`E zMVG27czva>M8j^oM{Q;URW=0j6GyZc+CE&1jw zD(hgAG3C=&x2(vQkfWPE=?%Ot-9$su=(PSQxzosJp5LS4+Bdi)H>pB(r#i5o5bS0l zzp~pU3~8%dHR9!lVP8<-fiwS75HQvEsRo^3?MF^>)EexCGi@ASrNT>~#2g3~gL892{mVyuPR4ha`L0JS;rM_|3cxYXc#if>PnI3z zeyUA*wumluwWLgRx(r7V^3QFEyHwr7MdBtpO%3(nVV!U3?3~zXw^@>!4vPwi<*_Gh zCJ%MFft+WHY!+BoETNM(V32-xq+OYuFKSTDsth{~rY;c;%+dnm8H{JN85#VA_wDdd z+7BuGfOP8NIpPaixNfQ`KA?k2r*neU-18BmKg2zRRaGqz?5#`)t5c(--9G7=tA26A;xAA*MY{#4NTm| z@%|eMH$;XE=Ac1^y_UDZ7sTI&U})vg;?Lbwv1IeRsSFzr?j8YeBy5P4k$EUW*v`yx z<(K4tonn-EH9g;!b+kO+4nMU&171-Uf^O}nEwhS<05QpBA%% z_O4JTR?eaSxzaFrCmzeLU;PL?>vm`mnU6-NZ1!MH1h&FtQIAxeCWjQR9lxFqKGJ>~ z+b;PY-!0cm<`o;rb+s~U0_`x{iSB;5k>BEY4ESQQyXn$V^sn~|T#(H67#LxuE@_n4mxk0X1s9;KrZIHVjSc`^`%cFM3|-J>9bJyFV|?~oaBQbv42QWQj`(FUG_ZNS@-w3=p` zG4y#wx)qNI<>;d6K_J&O&dXO&wW8mY6l)6XrEsC{I~&osfxcF4CRYmTvOM zqE<|q4vKb?80sPP*_|jRt@zV2z}jN32m@g>3_C`M+kFW-UknTZxb!S-J_J*S z{m0C({R<#m1E2(HV!$6UwW37e@+kstkv5KIl%q%CZaKwV0&DkKEB$nX$b(%=EsoK` zO86W$p5Iy8`BB&YlFV3wgmv4N5U|Pc3X9aPev3l(w%qkolbyk2F9O|r$P-Ged;S(1 zN#*Op1(ff#yFPYuIsl!M_sOso7Tw8=gE1|RUjT@m62}+fc=DNR5(@&_98qHtroT{1 zYG27jg}UPGmV&?^&)jiam3rvaDTZJ6<=QKIycUr2T(#blDi`=t&ZjDD_n!sXy&qiG ztE8%OA7L3|p>kf>Gf~L(MP15xPh-@;>z7sKk)MP&Z+$377@II{Wsc_$i!I>)=ZWom zgQ@cG6I8=~_!ex*#Xgac)_8f|YQfAYiL+fB+UbqIYLj)9UHHl4hVsY!Eca7*>|)5# z3%lA8HLxkRLPgE!=FJq$yM(Iny-!c1X{z`;{AZDbG4|-E#;@k^q>g1#Ltwo6PFIyb zv%|&Z^TE2+-pw;XFeH8$#(0fU`FEY5&O5C=Vp%$m)^TDBy&G-Z}W-a1M{A@L|l^5pf==x>av8Di17jj1V2Sy6dgmoVWI zf>Bj9tA|hNmCIqO6zZ+47rHSe>6cbe)>3d7D~Q{27S48-r&5B^OKSV=R#NrMwd9T^N-7kq5V&ZVa)x~ z&_tw}u>fj5R-E0S>P`h9@`(f}sr&_Z-*6iUM+f$%6?kW5)kURhm&fU14ij6XyZgeT zb2Md~he_hYXw<3V68M~=8_|9AVt;#rMo`RxS`fKTfQVd0)j=dlkbaD+e|LkSr+0|g z_dP+IqA;$Yf*Fjo)M&YZk5>4D`g`4+>K{0bI;tz zXDE}| z3uk*>(@#20XH_{n73OTdk>Pd6ri2YSunwixwx0U<>O(4&0IF+%U9GnX1Oek#doZ%h{8#HIkHFOc~Dr9$~{)O)_dA!U& z?Lt*cUf>}7@3gp?kL@C5Z=s{7@39uN<%k|Qfd3>(cmc#+Ew*r0lx+6yY|FRfno za~nIM2(f;V$gKUQ=tYQLc*Bfe=o8;wKhzE=en(!lN&2`wm%+3>RLr6F=bfZM&-${| zSM4|#k_3UMUrc`lGYoLdHP3=oVVjzf>mEa3{xf;v5A#@XS7q~2L=eAqXlSb?LFk*k z2x-wT4(>edA5Ru3x@grMkK(yY#{3N&JBIDzoomuf7#_ZqV$@6l2@M0TS`^RS-&5-~ zzQ94YUf&CY6BW%a?fGw9Y=hMoK2<8}-MQ5R1XO3!E1>^9AVVHvZx(d}11jga{F+mJ zrfNP(YkF#%)aYUHf|5}WMG8evW%6n`mE||Jplw*$d@16eUO=gT*bbN@KSJ2M3R|h_ z)VIUQI}XS05w@|5ck__(ONyo1&~bX5%Yolm7cH&hEeugOV__4kZ)=`DK}l!r-y5q$ zK=6$Mr*AbqPoJ4xzE8NqESI&nKc@PrK&PTjR6Nc*O;iH9J6% zY8{4%0>W5#b9fF(G2_~yV3#Vm-`zUcY6ZNgvO~_~hiXP|?u|%sC|$b7jh8VI0Znod zh`Qahg$D=|cfq6rqUBwKkLhH_+r%Cf#UUF2l`_-ce~W%J`02v_<$|7riHc8nX$z20 z6@i4B+Sel?N7G&R3B3Ft^?*2h$#m5 zt=7Oq`TZzG<3IVsWR4nWiRoOiT*N%_xt>V;bPapXlL4nSV*sRDTKVM57Ni;BqY_zO zZe-U3Xwd#2bxr1iqi)`9QvK@*SLr#0E$Ts)E)SSEj0E9wUx{*rdplG^{~F7}g8CKH zZFb2JGtX_0fo1bR#g`<|Kk(@Da^M}q62twgcnd@OI&WrJwyhr%ip$yR$zk_S45a5=wU+@h> zR^DKX!WemC9(Z_ou*WnsdIsb*wBt&Wb%+i$m%>Jb@OYegl<#)J&sgHdF|Y-^cm{#f z=5a}YJ5qXv@n5hs@Z1#IS z6C)lqjvsr06O$-phALF_C714Du}uqjglqB&Re|>AFO1-5O5?H%D`}9?d+lUI?I3U-p^WSgYyGFtH8> zkr4ZAvnSppRV>~}M=Rc7QzTZ80v4QKO?U*P?|W8d0WLIOo^gUz)Ys=bgi&* z@$4^*W_(78j|gq*Xjha*bIggXoR;@0-w`T|cJd1T-kdo1xP+{{@NZ0voyN}1z;ial z8Icxi;bfxDqM?C0n`b}HUX%gA`~Z576p?JbnI3x)C5qx`7wMGEl0{U=Ed3W`5v9VN z?X6E<>Z#>-pUFA|m`^4vVcVe>JgCceuToj^1GL1YebS_uNLf8%h6^ts-MS9~Y&7&hFZ@?g-ESH0;=7h)~5 zi~`szTHRU#i((_=VN48I0&tUp;)>&8@cc|re@fm20J#GNVcb4K2+IB@4Nb?e6b_pn zRmv((H|k<@Dzd6sK*nmh$oh+fZW&>>+uUWz&1~w_5nX^Trv*src2PaQv*&z4g<^&^ ztJL6bGt2C^<7O)a1_as)oFLh3>In9^`!u}I6`NWclK{RW0__J#{J1dqZj_TFF zG!{5jn8myjJ%yfi7m_nJu7NqzjTKO2D@bVB_%RGhz0IApA*At<)Q(F)(GW*KO7YrR z2m({!Lq%ogJFKQ^N**mZ2xZ;6?>Yo_s_02hAVbUhG8FXxqD!0pVly@0Zp4+eH(zeV z{aNxpw4c9kPf{f?JXr4!Ie_I?n}|Mp4g@M; z(W*1FadM_C!Hp}NX-lZ?toD*?hL$c#on@m%Axc0=hE(}{k(?#C*kWQja}WDlhd|ue zR={a&I%<*9-)f-{wu7oS+{L$nfj3HKg%ip*&Kb7>>3)_Rx+oC?2cc}p4aB#CkSH7q zLHsM6*fve#xWjgSgswxE_&x5xB7_bp(pgHI{yx-eD1Dp)nOPziwGHty%Ut+0{5>oz(urzuUS_J~1y^ZmGE@-k#3 zq*!okHwiu#st9!s#EIJ}IVpJ#P&`-^EjcWyQz!x;hl9od-OZv3z=zutR~?SPilw37 zlI00}2;Yi40UQ|Y|KR>g6yiX&AcNN!Am?wm@_x;atbf54pjh4r8=jczfuC9HNg$p| z;%z}3*QCi6l`s}Pn$)JEl`=uWTEQ=BOGDY47ag5ywwk${(}LY<%)4p9Kjd#41TnDJ zworFo1o9Ez2tIlB8%3q&ZpJ+gsObrM*3zfO)4aDoZ^D%&w&X~xA7%{uN|@O-XZ(&X zXkpIb9i3R36;{Y9>;V3e#u-rzllcLt6*FD^gZ-iI(4MABg+(m(S62xg8p^>;a7d%sB8BzfS zk)%DScOe-I!%{UmbuhUjK^Yp-U2=42h+`NOuL1t3L1|$P7DYOFQiG#H1Yy%qED+Hl zCL-Mg+3k{61AISNMP@RplW@H^9X}0^7F2eyzT8o=D}JXTHg~qs<7D2&>Z89?wGEj- zw)na|4s`C0!0q;|k9~7Vj*vELIobqZy%6)_K25S_W(+M@hDYy{-0|~q9{q}MBApcm-@`^n+`yy}#`1Dj6vVq6=#r}H(d0ohw*1W#o@t@tZ^HggkFxmx!JV-=Hn zLfZUxyQ#%1&y|HAtT#c!8e(NVZx$8;s|^eR!xO3Bz3}w7K0q1@+Q;hfeK6dTZQNlB z=W26oM?T4Adb0j;`d^+z1aJGp-pNF@KDLx=D6D3s%mIv)kd1yRU2m;g2f8k(ofGi-S`7%w!$Nf|uzb#J(Z7neCCHT6q! z9mfck)e(m}>i&)=Ye9?H-%Ra)Y55C~>Gv!>7K)iWWTOz&_oNnDor6(g{RHxg-iZA; z@`~JoqzA!0=7b<<2p+jlI`u))$_WpuQ8+aMoWHouu7_ttg{ecLhL~eBbzz3*o2vLG zv74#~#<9oymg7+8j$GUTnZG*YWXYJFP=gXc;mU$+d)@MhsUb!x#)4lRvAmH3VQ9*+ki5?Tk6F{T))JYS*Fx(QumBn%m8*wDf z9ErjQ+^VP*kcIXJ0ED;XOL|tf0@569`zoSmdCnrE@hMNj=6CTlYYnj)jN4WutnW62 zYW%|~W%)a-P6s)`G|t|>I4xX(H-javxp+Q7r*TO?k%Explg!omMuB7t5bS*wdOlY_ z@`I$VCDO3zI(dKu%olLl+Rt4=J>8-h^*0~}j@T0RwGvMvSggPL5E1VkGrTB40De{Ld1*fT~6+Ne^sSN_E7QGGE!hmcBHPm0Mm?|lv0gzS(S%KVgS>WSu_@{ut_76JCvLtCM(ggmx)PpcMuCtPL26Ec z&^myPY7=3KJ&wOgT2sz1ZV`0g2^jvmsm1L6y`49pFL}gFpRc6k-Gr2KGYdBBI7&zp zB}Gk^r4zt>FiYAAkn~|~csIr+HiUHmC9D}h(HwQ_IH^POUMIKtp1f-~pqw&ab7@OE z`sB+{KEq4>Uav#7h`<4 zt4G@9yaeL1e8@tHZmNiJf`huk)V$iMom7sTT{`*tpSfl;0cASbtB82^eoRLw9ar7M zNqtiWisAx=1xNht07}qjDH)o*kT$V4G=af1>a{9un2~uss<3leU^##Eg>o%kr(WqJ zz5=02a~nAOW!cwP%{OmYZu%r_!r#S1DB>kVHEIh)VHAY3vM(!Pcs~DP&ViLw_B3Ej zeiVuYI0%i97z8=`z%`aImVhR$^4kGpJlBmu-9+| zs7M@;^b$2{&07HyCNHK6m+22{F>51LgyTxyM-UFMJ*wT$cD6h^Y_ z0~IY@WiBK#1NP0^&FEg(r7+c$1Ttq4#lKy~w}U6n|kxrs=NZ6=g77Tv;50si-wKbkCWh{&0F--q(-y9;7awKZxc@%%wYB%1F&`n^geqQ8k2 z{J^v?NrRoyks+BiCkw^kK8 z0jrc8weDY*m|r;>c$HE6wW4x)dJEO4>Qn~w+%ba4K@DrV_SV@IXC)4A{^?P9dS?cgH5jfD~BMdA=h zyha@d5?gP(R35|TfJNB`F-pG6Cct{bxwbUrlS;O)PjU2@Vl3q`EIm!_kF|8R&HPIi z(S79@8vn2mkKFr}gWI0lUDJqr097mmu6;E)$}cqx5(l+sFiJiD0)u5Eman6`)=wfK z$!mIuB9*JH$)`O`ag&ENkaJe)J1<5IY z-5TR$B_>SIv0Jsj=qVVQ+%KwBrMttTu6UMD*)Bml@8xR8(w8f*{MW!djkhQjnG3ax zWp1H}0)Y)5CIVlv-n=VfiGQcg1pnyBgPNOn$Xh?-?vQu9>z<)Syt8fN=TMAEVqvpT z_GLe^5dN%d%`m8)M>nbHQ!d0ctB0!Zs)L#rr;n)F2-0P^$^M)&S}~+dk_l8%bI(vVoX}WZ8A63`GB-U9>g?_TE`E7aeZ0gsRL{lxr8`jg(Sv!_&8bD zIUbZ)sbzX=Evkjnz9_6(LuEW_&dT$$FbGG|FGqe%D02AEXr+^(Da@+zK|M-&|rhXXX&YXtaes|K6WN}`$@=zf)h(z(ypby=c(1@zGO@eAmp zVcxp1m`u@ED_2-GhA%|#OseHh_-}|#iS>_nnQ57CJk0fHkc5SW7j5iZZ=n_6rbmT? zGh;CTYy`H?abkIFr7bR;vC{+D496Q%sY!&YElBFvB-4wp6z0;Ys|>=zyu8oqq?h?z zZ-xK;Jw5&>gcJKPYV=m*-*2VAV@Jm)7`yMvV8iRRC$NulPm75JFp8msvf|iTtyM@| zoJV;0idwDk-0XbrG+7aN1|PWLGNhk;rlW%VBEP}^}wO1rN;D8V0Q*#HzA{d!(H zZUsYk&|`TT_8cMdRUfoL8d-qn&>$P>iR!XCl7n@T&Yvu2@x3qcRQaUrOHs0wLJizK zFuM2gy5pt{0f`Z;l@Hd9g)SkMo-9PfehQs>V{(6|87tCx)xIe`CExlVnT?-`IVJ9CVMZkVZ_S2hEf^*lZfIli3H{VW+ph4iBH14( zHs;Q{i?KMrQk)%=-b(*ecXl_`ZbYBYsf#I7-%Y3I$8IOCR$4?)CJ(PwXOnUubbZyb z)rw6-i81t9QY>pOodGXVdH}xcRz#LCiJAubIcN8n)Z=E;UHa4a?)1 z5$4(PDIw|#%@XGf`_uJwDHac`!-)wx;+xLR!U0shRR!{f;+QazAItmeg zHf;&TUMD`m2Y^R@`;!1N=D5B-_Uco$?Ykj8AMuI|9A&V6<;(rH>PUwKT6_L{M?HM4 zjxS>0Okx@{OoaBuOTDkAD1341H`r#MW|*rhGS&2g{pBT>B=6aYWWegY5;X?HtHbTK zVCI+nqn5Ws{3n@&j|u0N*Nm_>L-WNbnt!wsYhfzCzqd?=eWNI!3RUkMeZc!35<5Sr zP)V`vn&vQCGmv?!K%Ngb{B2&ZR~lC@27OB6 zuaZAI4Y1$F@aev%6Zcnr8jkZ+uKKYLpJp7ojKuzIbc8Hbe*5~(wolj#cK6`a=Do$9 zf#bBapP*kj-&K)$Q+M^Sy$N`r6_-;A>#sOjNu@r}3XI@2s88Xqm*tbfL0u{vQx5 zD%bUdY=&wfeHzz=KW6UDV1NFAIajXl+QiSc|D4~S7LamN8%#CEzI2weWe%-ORTAA{ zt9+_s-=4zLq&t~dsa8>%e*8MApX56HAdmL&pdmd4^P4f8n;tGpoEw0eo^ z>6`ib$AXfEzA%D&!zWpMt9s4Kt!#+ux24y9zHjU2L)pO|7Vyk@8EenX0n)ASohANcr>y5>ZK7+8LV$|HljYz5z$#_-b~7F zXh|)5-Ynm4C~ePJo^2&gUt$Al)1UqS-F(u+Hbh=;S1v+K!FWvppMGX_x z3%3G?SNk5KJ%@rtuSdi|(cck6Y+qhDP?)K1W3_6J7xd%c2@2JOfwor?6xC$aTc)f}3E;)i_K{5ED=E-Vm6a+bL@V zA%Y+kb#7H*pZfLAVtgB>CxuZ-f*?7q_8e_N2{ZSdi$>9<+29F2lNaRG{6;zqs-d}r z6dyCWCVuvpQu_Br)4x>ZDxiD27c*L970KN^_0L4cVphU3JwWOvx)5mxvg_X&%+a79 z7m52XiG~!#I|m{EWadpV)rOD0`+>-8w3Oy?_I$#LvHqc_Pva3Ju&>A@;FyMi|I@?Y zE|~9TnjMD5*-%ozM@_3Re@TT0LX?xmmA>5zdR|HWaQOWdIIX2?!6KO@C(IY)|(kTiQsTu zov19*Y=d=7GS{lOTONg-^fttjc8k!2Y&?0`Y+-PorB4)A+VfoQSgioBuC`#Vfm8P$ zVJWJ6(GOJ(H{BLd3m}OPNYJ+h>aJJO;eK=`IVOIUL!ZBbnP=to=_zS(QpU8~9G2-+ zD#b5~CHoGy%PDMPE*B4SyYRI744v*%wP|dbGoSEGg4K9l`p&SQ19^?M*Z)}3+)U&? z?G5iJ*-mSc6u)JyRsqul!T)OFZu^&c&pkA8?V6{{ab8#C>j}-1;0K4{_P^O2*<`Zb7pt`$CospQ?oU0N z&WyK9Iv4RW`M<_ue=)>K?n<6ZOwINQEmw~<}G~KR1r{k`wjWPG`Ag1F&_9vM`EgnNOXO8dJUt;{r-=D zQ+o6T(^lB*XA;w`O=0nM_hXpJjq6P>&8g^eP2`W#Zt^!wUJZKE>1C8E1YUiKJpmHU zZ$_8tpR|-#3PN38h+kme_w7?(T5&F9Tk;T|pV%EM-7YA%o^soM(0rQP;7~AGLPeXP zvdgoM>Q2_y>2h^6Y!pwQ14=*70Ka_U$)RP6SpFX>-AfHZLagBz5Y@jnd5gb*tw;SsQwZqpQ!fn@6PvpO?-l&x&&d06R zj|r?;9@pgh{Xl)L+j?V_AJrpEc`n;}Q<@)j_Ae0151Q`3aGJ=R`D0s<{>!s2?mM^Y z51-weh#__)`jY&FE85$~Kz5QNrU%?n!DX0Z+w9lI;FQgX*gjZF;;AP^L86ibtNjuo zo{OYR*qS2D<-aCrJ1kY_@4&dtAH$D~P}Iay^0R+65PYB8v-59MgA4T6jV-@+qOeDM zRL;4Yv?)p(MVI3F-Ejl{j*|rR_Vw~O=gmxH309|Q_m6Qm`+6Z{t{sP14%ETcl;mDv0l&s delta 32922 zcmV)?K!U%}h61>T0+65wRb^XlNzUA{rz`<~f08MG`6BcdyXBTl@p`q`26v0y*I>K6 zTWl7)HQjNzzFvP9$9ehB-ST$3THkJi)opOK+7PyW7p$(9x4YHn72)~YdKb( zyWK9gsza?m{l2{1t-dWqC8N{-bpJ(^?>oX4UoI}cE`!CVt*nA%qSx!~QaITS<>e~m z?$)>R*ot#^PvfqK}eO$yzq6oxS}(hN_BN}S60Zy zPPiqtdUKIrTEE_`zN~H`O(zXemFQM~9OlxGXphI$;!lyK1m%kCs<~Qi@2-XH?c!!h zt@&-a`6LU-`hItJPgXy!HjD48b!ns`|53>-(!EpygkdVh}4+)@Hd~Uw;!Lugk@5alIxxjbHA?VC#By zOBV;q%By@@4CLrkukV6t^tqL$C&r$n;_~E)fI%zzc}-k|mFo3URQSc0CGF9@S#18e zT7SPKwIrpy7R~*>S?#KrLL5MU6+`BU@>(I5{jdAg2G!?4qPsGL)5?l-xFyViO7qXf z&9$1TB2!)8Z>W>nSK-NITD#rdmeMv?SO1i=d}MO1;Yx6~UeN`zA#F90xVc?igCKH1 zaKD9$6Av|p8Jnf7&M=m!Z@SP?PB^S?zb-}9U))|UgKw+lcgh(Ott}dVet%DwGFG=D zgMYrima_rZcl4^)Yq|j5sFKdWDcLXUZ&&NfE&Wlbgvk#?B}{)TuGg0fKz}G@$&W)R zOM4X7pJ~6o&?EicLXY+f@0K@ITGxwDOEPn-bAPbi-Vurhi~HSI(n4B~C8%eMYT^40 z@f_mKVt4sf4l(6$et9Q%}cX zceC8yU+?IZiRU5=;c_faFMPe)0*=GodT|3#rJbv4gb9mBBf47$x^NzTG93Vi7ICF0W%BDpsn%Bs;UvP4Jh^?zOI*&V(_e>%GWmsAYtvte zjWqeCSW6RMG>tC#RZ~k7UN)3BaHLi_?D@RB+AMDF=!I_y3+L^nI+&zGG_85R`~1Jf zcy_bh1(#nJn_zu^M|$tZq^x&emm3HLv#f4?yCjqf)*DfV#c=!UpLbuEw{*8TO>Ncn z=#-m1%_D+Oru^aH6`mAc;-n_I%w zyJ~eNqI1!%`rIz$3Ki8y#YM59lijVhpI5CCO#HCT5CU+#s|AFV9j;kFNUHjIcSpJK zZM)v=D0|xWPGzFb@+(v#dIKj{ANXQ5ebWQ5e71pq8nXMk+Eybyk0(!0hLK(&Te${% zb*tt@Nf%)&<*VT9ro5?lOD)_v?*AnsIBAh9Dc8%zw`K6@dU5*)`RUXhX!xl;avJR@ zrM`$M1@E_VDGa${Jx4&SEH9bsr8-%Z4?1gg`CQ$4yCUt=rLwUCms**6=1%M0u6M!W z?(TYjbtxa(BNms#ZFR{lsJot;Q76`vlRYc)mTJ}OKY^V?-iW+Kse&)YyN!^iu64u{ z8(LMZ92Bwt+wyvS2dL1c{>|cdbyMR?PI8k@rkBsnv*)6N*ifHH9 z%v8A827fI7L@3jC#ocO0S5SAG#qCxE;2X7nykScxE25pAK9;kiq(j6?yxdZQaGggj ztZv8wl__WHD`^ovc8Dgc$0b*n!7X{`_;S7ew75p}4EZRYdIpMcDy*eVTZFW-@bT(7 zF2FHqo`iy3kUhj^arwuRyhr}AT;4%0A^qHh=rrZn8gPhU$KIHtp%*8VyuV%jQ&(<( z%2{b2=180}?$7bwIXMp?~X_qmn-!n4QyP(fftE0)?VBts$lG0u61Vv|OrwMaPb_75ybtsy{{j28XGgVvQU9b( z``_j~#)5Dv;>2R-{^m39NKSs)g01fUneBfBncST|h+^62vpgwMIP>p z;FxEB2~u#7`{4)2uz1Gu^iR~>Ty!%G@rf0pccq0OpTrSW|01_?$I#-Gvs`>VK@*pY zqJcoX?i{Z{8Xi~>CQ0^_MKIida~wr1g~=zG?C`P%yu>_y03J8~dPw5*2TcDZOybBx z&laekaT;YmLA4<+ST6dQfQVv$Ds%@>eHuhevM>T(Gl%d8Grt9fa?DRD3)taUyvj=y zbf|Kcghl+qgci?|7s~IF#JsSz&E_-jNM3}paP6%w2`h2& zgV}OwlH-(%&lSN7%O5fxi_u3S53OCt9Y@GA^^{}}VvsJc`Z#@mD)l)fK>S*&mPI$r zpGf4(%h+;AV|?g6QOi1LqpV&~d0(}BQeSqHzmRS%v%yim9FbXFhmOR@m?aUH$vO~z zF8^a5m}wN8PH`laxgVUcf)nGx!)xtcP^K&fVUm>Q#l7Gfp9~&FmMP~W#WyeetG5=2 zB>h-V?!uAv6ioSlGyb?)roXQj92cejl!UqHQ*r3$Wbz`9k4G^e@_b~ASl*LR)}wza zkKy3wkc-k6M5kjC?`7!pTrR{Vs=AX1W8#R1@+kPA%8VSv@=QORit@Gv9$5aHEKz z&{2w9%S|hU>c_{0nrAOIi|tpN2fM6=ZQi?KCvN*zkN4EoFhc&$x*NWyEXN5VgUBg9 z+X?CSq;s~olsbg@+^aN^O<)fE$7dt>#BSBY07fzC7*VTvI}DLV=h+% zB}~Z%YR;VS+vMy*&K2vsmD#i>Bf1}YPgIOJl5ZyAz0uMvfLsrr<-vhZySX-xRgOQa zRi9LUz=x1CWB5Jcd^DeUQ*Qc|W}&&3Yt=uAKi^a>o^XEM#4mz!SSgNP&dZyz?~Gk% zp-#ea%K=3>&4mU=*&fbdzxK%~Vu8Nqyx}TB z(8H_FLDlRc_*<5bE%^Zb#l_bXqM4io@&=T*sl3qYg>|CGhzswa@7utz^;~q>T@K-K zYC>}a?z7{onuYYiDKa!AXYypZ-i~(%mk;gLgC0-BvXhA7GJT~31yJ4Z_l0ebCgp>F zkzt%pT*ya&mK~w6FcYdf=l{W}JRFgjB*;DJVKTxZGf`I+) z9zQ@$nwN<{jmp_EKYOD-$gvR-PVQ?ZF8lN``zURZ4_m2~%x7-UK4D>AHmQD0{OrxC z56-!pqxVrTO#l3ik=p=8dH6G}nsx4jq@Jx4r>js+ldUR;Odp|HdOd2KevormKS)re zwp~x^}Gi!!s5g~RJ%S{Yd&1ju4i*{wHqvFAF5Fw zq?4c0LT)io2LhSzKF}!~Xx;}&D-n~M|H-=;AM1*IJT>|5qja-su8@C!oVJL_BJKI( zWCmU?VE71!h-Z1hqSi&Hj@n0Pny_Ie7g+^K_#l_5KL+eq%nSaZ+NLZgwpyL#tzG9n zQaL*&;@1yyDnE__QZ#y z_^H478JoiSF*rot&XHP3m3TOu~o%&1$F z9gbNl6YbpVpSWSiJX3R+AFNrbE`Xb4|G;(cgHyy^%77(7A57bS$Gd4@j*nkYf|qY3 z<8tZ5h4{@@gG$Mb1J zSm@te9_-JsBj;lJ1D5ky)n8idJ7~>43Bmlr^k=IM(faswkYnd?rB$ofjec*{S%|n! zorj8DcP85`M%9vkFM7p|@1tLF&vEo?cD>xlI!C!TrTnw=HC_IBI%wWCZB1LKKf09u z*~B?LX$F;_9;zSm0oUsW9lK7JPR7jcI5sSOIMp96n=8bz1I;AMmljUmAbMsK$`S93 zQ(6kxz~-J<2jXS*ySZLZL!VbENLtYNzFJz&9_3x8OmCcjIiuszH?HZR{#!IRoY2tE z*InusG;?EhWC@ex%x7h&RW@&fnBB6pS|Z?7I_0M)V=k8eyu7}@S_WU2*LSX^(~Wq& zzWw5txc$1`?EE0VeD!!l1U6fmF1@p}DfaqaV1mOzikvjloPreBwftK}y6wzyth zEp|RH{jckPZ=PxX&ZDGxJc+9>x9g41b0?2v(CIoJ$>sO;2;7LTdb2#oSKTdd?ylv9 z`E9w`uF5xr;L$g0;gE~Xm*94Bv-F6({JLIUF1LP&os$}TUSEs;y!Ch)bz9(*e0jgw zo`dMG2v!~lR?|7byT%vt{mgJInmYQ6m&r_7QyT#eqyT$eo zWdJE) z2`tL?&XZd5vl9`s?gH3wuJreDn7_5f%$TUPMiuOEOyrEGM`pFpaVXHvQ>@lh&I-BL zRrP&;pX7_JQWgbuNA=N&8eeVA?TzdS_?RWtUg|DazW(@h(5&m% zxHCyEQ+Is(diBpIyHwqq;E(*Q9; z=KSdDe&VCk0JFSrI%T`Po9TK^tQoz;iuXBAEOsxLPxAY{E*{k{LDe4}db|~Nre`~` z;79a@sXnJ*O82=5eH{sSl#e>I8468!^ z!}S6?(|3@6#f$0(|GRz*{Sz!|Zm7+8((DXhqT0iv`mz5;P1gao{^@d-U%mt3w3n~e z{%`bE%FSTf)3)Bv<=Jl)MM1txPTXaGy@m}l zOE30^C^!{y;?`kI0UMZpc}{uNPk)Ch4ZC?IwcG`$$gy+`EEdw>DQyHNt|jZf^R|2gvH9&3`NZOvNts> zkr$VTXrumoS+&5nz>zlKVsXEJ`x-1aoAt(WC`jLw%k|C8;`Zu;wB~Akd4IFK-EFH? zu5!8O$7tH>_Hw=1EH8KR`Je6io3s8P$7Q{}TwH&=)3v?7yj*V2f1c_U#Ow9$gB+Us z+dppC-~F5@wXDXzr&^#AhL5-2vo>-V=2@@spIlivKyB zY#VKt6Ktg~hIQ#vb#FGP&w|bAeUGQLtRLo27oRQMUI)V!!su zDPqB6%#z60QS}Oci_}NK zeIetgG?a_9eDRX3@O3yncbriEfpHHcxk{~IsgLgzMS=QW)@j6rRxYWnk0P8WpRWpx zg9!(wjET}MiPeH}0C6k-?~s)($YD&OT~ zxImoF#2X-g^)C7H<TytfU_pS;J@9)K8b_Z@Q?)M zwne_E`ZZIYacY5iki@+33Xb<)c{U}PfLFhf%L}i6{O4G1iYA|$2n+4k9^i4g^MtrY zk9l_Vb%7otHJ|5;CU5FTev5(J!L@vXu*Aw4s1x&be2pC~{Ll`^LdbJ*-EeOD7-1@@IV( z-cufbm+9mX9z7w0fcmv4Tq>xRb`RNGt06#%hz1JC&8HQ3f~zb0%$`D1FpP>)j1)CfIV3To%_ z+>RuCu(?T0#x=&J!DF5sf>>Oa=V?cACak;!yjP(bey$EDE8rQhvfir6b+sE_d^ie! z=HKUU$9Xz^IW;7Aq53G7VKX~+)@JBxd=_$D6VG}8JADN1KdW)=RVkNr9FX`FH< z4}Dpfjswpw&+6=pC_=#Jop(G&ru%!^nE?bYcF^X`B_4`y2+&~p{R$99nXS4 zLn>;(=Q-l%=;P%Gq+A5+87-eI6TdcpgP}9TLE(Az5m3MJ&6i7$19b=I2Mf~u8OEch zH2(V(KfW6Nk8QzSb(d^YmKNBglL@+5Y`3c~w{okx;PZNOgPgo8tsdr_aZeCB-)-h>Qe*ud+=ftRICV9O8*XC@vG38%Y`P)BH-2p1+ zI}VXYJd5HYly4nWOFdGb$GTpBn9HI-F9SSyYXO&Zne<&o8Sf(15>@MKz5LX>vQF3f zRBe5fzSm#C;#zlNI6I0Ptz0}@{fM0Omsfz*v%>G;^TWl%t6E)ezc^~(vl9_^y(}FlI1v{b zJKr(NnYecM>II-p=nu%14OxO#{L;37Z-Shd`n!x$dZnx+84Jd=J`Wtv`dD6vq5vN5m#iH5vvXo@;Tk(%{CZUL3O*G+w_v5&s(6HM>6G; zBu5c~<%6%`DX}Q#bDLn>ZRhd~=dzi#r6)I!h)$d&1T;bakUa4!%oK4kefd0~Jv=O8 z{urP0kXTNpLRw&7@aWrMIqgc@h8taPt@9YH4d*^9oz{$`xYk2|(I2s;GVImO_&5!$ z2FyYEf|#S#qCZh9ESs5*T6htJufve&nM&TV>gTEn7j&jYtb5d$Bc z2C(Y$?vyL>cP@)12#M_{m+MLy)>Av=L^MSX9OPWnY%ym>{*TV(`w*UJ)62ZRg;Hu;cD;@a`vD90hDg0@yP)y zmg3}fS3^i=51i#MYAfIJHEXJ$0>6uVH3JT!z5=2rRXhF#)hVgoKJs`<%S{y^7IpS`rT*nKT@KetMu3kM}{w_hDk?G}VXR6TMj7 z++8o_gRsl1V6*(M`_)GMX=`yYPG(tq(PZT><)4fNpc7NaT#VC;HYuQvFWV$QTfA_S zfadnnO#-lYpxetg3BYq+z)693e+efE-StJB1aOy^aZ+GyU&u+pw0S8f0q+c*sab_| zI>nKHCunCyj0a--bs~Yy_P?{)Nu2)h#jN*;@)m?Yn!Y!zcI}_M;B_{){Z<4| zP>PQ`b;7EtP%R00s4&b`7Ghte{}X6 zoX-%O&Copbk~;2%?I%0?ORxU2Yl~E5`z-N)M6-D{+e{Wdlb?9ca7MJ((b{km&Mq3~lg|=vPez*|fKFMMe5yqQ6W(&i5JWM_YkT^`l^qv3|4-=VW^f_M>g^p6th4 z;yK#C(GaiMezYCl!u@y)yrlbaJUrfikD|}p2hGi9xqp0pw<+?^_A|B_fuqM1BUtpH zVg!r7bu$X~cOPe@3EoCjWBk^}PJY?oan%Ub!@z2UT#u~eosx4jz{{{|%ZmC1SIEJX z$?-RY>Qa3UoH}guaH)gyI7sS{{S!S7h&p8N!=NtT^Wdk4_d4Y1(7g?Gx?C@R!<#M? zKB(yc&(WjG4PKxzqs7BV*%nSc8taXAhD9DNzI@X$IJwn(u0fMa1@RbLOr+P$Vu0a+ z#bEhND+bmx&Sy?Bu>M1e3HO~)T5P}Z#6bJYCMMKRFfobvRASJ)cOhRBstwW4JZ8f~ zPhB=7^lW8A@{sBbmcKd4hT80Z#)!?zH4r@a*MMlJ`~Hg4zrv|oyQm)?6S3M}8cC^6O*fr&Vlcy^b*TDeTA-p2uAT`B%Tov#2Dr z0e|ny%iZeR$7#`ax7ew7czl=^-QQj22D&NpKXFN&X0Qc@k-xRV5bCRabOT&OBocUCdWM8|M)IVtP zhVa1;PldQu1t(I~^QXTPoQ&t*k!F*VEM$zDo2uoDVGDLRCKk_((zT{~y{b4Iyl|Qj zn%#u*J-PKis{>Nr1;DpO_%<)xuPgQO>7a{G*Xzqa{_B3d6GN}Bi;e3=W{bUCUo90n z5TVl-^vn9&aw7t6aJ9Y+Hp?%|fBKU@CpUlh)$Q+#;7SZ;#n-*L3qG$mHw$my`g*n9 zdHuTE`%l~5YIna|t#AEaQ04U48IapQZ$7QB@yuhM?HT9O7t*~UVF#QUFkPut;iK}+h2`93k_phZYV~*!K813!fMC*MTH~TX%@8HTgYj{YU#q1+SdDG!g&-l^V?ty*p8jVSjrjZ^uYqvLZ91YlmUW5DBo`TN%8 zJ%a2++==C5ar`3O*YDSylrLJJdRNviS6FH<_7-nQa}$^QJpFBvAY37qLB)R!!+x>- z$s)44QIu=y)rdgMbI1ezg(45AJWG;?aQ_30@`RE5+!eXal!z0@W>Km$;No(#TJSy1$dRRN$EJn-z+3nKLmGzYB|Js3UYS@UlGs6j!ZB z9@sE?JoSi)`b+r$QSr>ZlJ$QF^ zP}3vOK4B2xU82o`_6QRN?hq!*OMmzrCm#AlL-EruT0DH;FmOKlhk<`X^%0gd@1U}n z=d3>VzOc(or-k}5v3Y5Lv;M{E%k6rz48Cs`cX!K8u()0=wpOEd2d2{;s}slRN_8T+ zT%!)4CsufY$gP~RpG@th5a=IJv%K6B-qY7S=4{W@&W$Xw+u&jr);y}^tymsg_Gii`Jg>d@`WT^X8-VfqwD z@ADR@3psP6cZ9HC>_JJsxLR$lSAW>8Fd%Kf@7wk5`RMnzf84IWpRoadE^e+-^jQ2* z{uu6=?etyq!6|>@7whfi;(Eb3J3J(>c71sc$>}AXL|n%=b<)r+Ue`$jbbDtf4f`BS zx3_oFu;;wOlc)vm@A0H+fa}XVY4|R0^dutNzSffnYx8bT8svHU);=u4B%At*EfS*T zOGPP|$1FT}q~)2+Bp$yX505@!xkniH_{~HNeT<(x=Cywkc%kl}2%kHi=-a}0sc~SJMduF66H4kc??}4bv!A4UC;o5OA1BMY-Mg@n zce-6+18})RFYnNP>fSy0J2);G8UvIs-v~rW5~1#O zYSn3f>Ro@?i?#aW=LRyNRLo*nU)b|#7PseSgXBU6Kd_uV#a#H6enSfxRK1II@*W@M zPmju2x!QYLex82HY0*Fb zhSbHKp*i7-w~>@HveP$LaZs+d`L%lmHPM?`vpsfD&$O+pfKI!m6=k}-G zmA%-AKiY18HjCl-vgHZPLsp32%bCpS2dnwaJCat{nvL#fxv?b6<+~&&AATow>jLV^ zQHy_C_&!X$fyzzM%Z_EU*kcYj4}StNcCp_baB-i<7PsZ+gD$@Ac6Sq>7a*WruP+zZ z!ROWW(i?L7d3Waxw%aVXI}cw@t;Z|>3g7D$?UcvpYq`S3Y5izy6z8lN)nl>MHh#~@nDN+V(yRHzn{t-v zYMSQaNj@}q65qO7RX6EKyNEj+XeUfq-dbsfAh!Ez&*oP5c!P*N%C9VMYWZ$NHF)yP z<^1T2`NUF|%X?;?PjtgQ9;ZlbWz;`8{DzZG>U{)Iih)T+I*wK|-Asc#Iq#p&79#|2ZBb zH(o9w97&Py6jZade!f+`;)N2VXQZ2wJ1KsfpL$pJ;&QQDT(7?b%YR;8-(M}K=5b4i zetS6-vbqB4?v^)I%Y&Q69foqdxB-717x}pM&2qQgU=P2113Z|pS>G);yFalMyK$+V z_DyvqPcl{qZ3l04p;+EKwSZ(%{P=2L>(s~I7j`_kQ`K+k)?1xlJNX%>*b?M?mfz(Z z^HXZ?XzEk%%DSE7iQ0En!);Emjkf#QwW7G5+EK_!J*u0BLXG7vH?hYAY+!$Or=Enk z5&v>m|AX~ybz~dtyArfDj*9>++9c<2;%sVSWbTkiLcAJ-5ZMRp>iuT%cW~>5dBEiEI@T5{2}D#^u>e{ z+W+Jvd6_Ru$orMm6|pP-O0M0hX%h-A70&7DeM-3FBm9I-uy~H2km~j@KVbvT26lU_ zpRfUQp6#b>hWi8lq^)p$%Ac?iE|2mL?GJ$Oo+9QzI5?LOMtr>bk z-QQO&LjJ=ejpYZfmeq+b8hJjer&Bp9@&cQ>eV8*(J$iK2zBqq8p}b}DA+X1EK7a@3 z^8up2ggyX23)EjqAAtML=|fHMo74we;4`ZaG{9F{A42=c>qA_0Vjp0hse{SA+g`-) z8TSaa*lLyz8mBMfAG7>5hzoY`NiKH>i(gn7x5}AXpAE>Fd>qav@x)o~lLwD@6Bi!L z)AttUW-Kk3%>;kPHs{3yvx)vl{!-b@^#Jp^e)HF?JN~n&zLJ*9J^lGGbf$8;Yd@1V zaPJR;+sVnAMH*eUrfNW5)Q5R9reU;4ml|vU*s=zh{`_kYeqaxWjRsxqO!y zwAoo;CYvA(%xi&T8kh&29|z{~&&8b|2s6wIX0Nd+^} zuCZVq_I&+K{E|D}m6!u{&IYc~O%oXW63^!12LFss-n7EAn>XO|IeOEEbF$Cp>`fca z?e0cP&g*~hW<$>D@=ZI=<@81i&f)e3-nZj7==1i$Sxai?!u8tP@aP{+u*P<76WkZu z&LtZ&Cw{?hD^cfCeFaT%5%Hqlgv1xicerem{m04{-%p@yA-zY*7X3U_@A0ukKT~jQ zx8W?2vD1VzgvC}1JjcW~+hag%gFQvV7W7=b%<+E?kvq`bVM@Y%%t9G>PtjnR7WwOM zo-m#RK?C)k1!}aH7*NxECx9C49q8NlYw&q2zrmlw?G3trqp#t9J-)&Ev-gJS$JuM% z89GzM_&$%1)tJ-+k)@F*QWB>>xG$F6btwuSUOn;Z7bJUN{^nc)#)41p5onCe=@bHi&2GR?kA(8_ZKSs(GHQonYUVc|gxr z58A_Jb|bu4KV(0b*-bbj+IJ)X?(j0dA?JUH2(aB=W;ercWT4*pWj@_cgdpDqW+r~l zUNAG!R9mFXY=)H?o%qN4KAy8`n3_cRZus;m(nMju=L}+npQRZ`>l;`OXpP zCsxtyg6F~<-UbKBEgz~0OzyS>$DFaB23d>dR1_73!IaW(in9@pT{VR8oD zzsuEdzc$xk{rOzO^kZ~2?+l&E_!ocuR(K!K<{2SR&gyfiwkCR5s;x<4C?3V>ldnVR zWo3B9^1YFO=4KC^?N8&VgSjpUSePFHjrmf7jMj=-!aHiIoIVaIWm6$7d5I9h+QV$2#C z*^y?9fh&Rwa)Qr7rcDzf`4+B&8y8ASp$u<4CPq(2LSWky4a6h?IY#h$?RD??AO{c|GIwaLSTQYDWQO0|F5w%&Fc-2yA9NiJoP z6}cqfl#%tgB;bF`vF4zwafQJaYH7J~1i2{bl(E(X43mWHPPFu!?7rfEC&t0@7th&&`oMG% zKePM?86tVg^0;_D&>fdb@nZXR@$bPu{_!8=ZPm*E>py=%%K!eqQEmQTzx@NE3_HxQ zqYOL9q{q14GhtEh3QTj6bc9hMe*l9^`+XQ~?CjFt)roCSmcI#niwPhLceV=R z!Phhj#OoM#6S%vfCWi`!*lW7>*$0`ic#VQ8M!?eDKlW+H+pQSkM z;)=F*8WK)|bfi&jwtA?}R-1ImNl%-j4mRx?i?%lDN{hBME+^>}36#d?B?IImGc`C= zZfXb~vQq=|0`ZWc8kn~nWgtCeDU;|WPc=YzrZRs}&|GD3VA-l+cyaWpI+41C^b zSia(hLG+V0OrVdj(eTh&!yqA}hJisPjRxVTFCd_^$&> zft7zeCkz>)u1)jag?xlNlZTBfCJCEdOcFZ8m@J;1 z@;&pz!c001fY31tvWWf-NVB2}cKA$MoW6gEf5`IJAg0`5=PjgsStGP&m@s*N`_&8S z#HYWNXaXqP$8u){`u%!((zxJ007Ay~K8`x1_X)sg-iLXC0AqL`1`po@NO0sHB0__9 z9|()r11LzS9^jBi=|00#hY0m=0^*F+UMFEG2HVc{}Iw)X#Xpum_hW;I9yo7ONBYF;BqpoxDC5*kE0Os+Os;$&{ zAly|hS!EFtN4s!%06^@xpThl*8_`z6Wg?9v$Y0w4n60)jq;A?$Mww^}0u@JDW($IK z$~FpVkR1}v7h52V9kvnlF4)$mHNTcN_(Y3;roH)YXp{Q^XaD&h#BwknsKkGP9-tA# z^;e*onHfhzw4D69bt0g)Ck$itby01i{9hd}g|dWb?>s|N^Py1`?(XLL*2dh(_@tpu?2nBy^z_miR;5boB$aBxeih`R)V5T0fKqm8%&=pm>a&q1l!|VWT;=h2?iSI8(fg1zC{FB>{~cu z&wT^sx6c698IHrMDwls%|HSc3z_w)X!+d^0+FUh?p$%H27~%&T$3d7h1`A=HvX|G$ zg-%)?1D1ze0dQty zVrZ?$RE8Oi34w~kOvHqMEu)2k8bq4}v;z|as>dw^p!&A-iEFK?4L;Gt!x}@m2>B1v zt^W*d>cLXBKgoaHZdVaN66G{40M2Pl46W0c$}p!fAy9Fc)0hyj)3i`fr)iUbPGf>V zPSZjFoTjBu>@=n}_(aE|bQiI>JaT}zI<*WS404*SYA<5X{pBHylSLGXf5V7^{H%+B zIa&uq>S-Nql&f_xV0o0Ybud_O>%x%k)??xPt%IVSNb7%yW9+jFp*PSjf!0Dh>gfJN zeh+6z+(U`?a?fT22rKy>?$M0kJYjrTfwy}xV^Ck#;OXAW2ohh-v9~|QNVw__zTL4* zi=6IGhf+h;@k$$4xHW;cQfpCIY1aBEU0Cte`rv9?QK03uh5+lSW`GK4r4Fc=l{9gQ z)Uvqq30Qy7R|>NJTB$($wfH9diT+Ylp{C%scuit-}N z3v$Wg#Do2Fm_9LDY0@pXOG(NbbfqHkjOp@M!SXar2=C1`lBj^x0^m}TiJ^^3rZOxq znGmQrEIFAFaC~Z^pc$%70tP7)1WHpa1Rzqi^of6Sm8lIr(S#n*h|=DZGlW47gS#j9 zS#BRis|IqeS{r6s6@k>RDp8bGRr)AhltEScSZ}H+NLy+kI7g}&7&EHX>3yh{rnR6- z7I!{L2h61;(>7 zCR=~Y!fduC;FMujTNA)$+i;+EYhZweTT?)m+vo#Kw-G0{-C7uVW&yM6m2`YKCQL4K zRGZ}maz<4Bk@RtZ3Pu|tv}n0!F1ajilF*{nynFV*S^lC9IgF9V{0BgsHVkRmBFvvy zL9R+U2VaRIt_w`e+SLb@UKJa;8U{Le)g*sJ{Hn#lA*|-0^}&Ix=6H!^4b4M1GhpzD zR~Wlk_Tj@ zN}BL}fo)}EUfPLPLvAd+0lBC*E=8T^F0dKr5d!r~?eEN2+S44nt}-fq4smc1bbxg6Q-}!dKXzr_q7|zAj^Y8mQzb3hL(M4z%l8l zQy-pHwdG8-J*mMk+0p4KgMz~#2bLm+Xrz&12!P5LLo6Q*RPq>NVPnW35t&Jbfw+J& z#KWYOK@xp*8N|@$m?4CpzQD_0gJTlz*>jdeEGJ!1GD_q)0&yCu0r`${kC=b9?8S3Y z90O5IS(Jx|WAK!{1St>HC&-Ufix{)wQDlUtAb;G;|Ni5*fBXYTrURb zzOzKrI|js2acBgEOGLv!+E6sifaRiLoF@z{9S!5a0civZ%}8TRU`!fDf|Ak*3=oz^ zNW^(*nBuK#5U)`fWT+dzPy&B-PO2Czy37v8EET_nilhCogTnh^8;J44HUsX5ZJZ|z z+z;D0Pkz{edhx?9(}N$jkzhaUz<_?(A%Xm`P4U(>_SNrb=MIKYq>CB{38ZTq2MMV7 z&}OI&qvD5z1;;QiVut0>hlwmNw){x1h>H!4J~AuRC0$cs9NpXBcw<`|Hg3|`wr$&P z+>LF!F&f+6xG@`Bjhi%V`|bPxZqCfjUd)_5=R7|>gLe_Eh6<-CJ|hNpfcrCGGpIa3 z6;iMR5Wng>85HWH5{vIm`QUT&A4dBcf!N2?S72}MpvpKsToU+`vx#;}+W?SXmrZ0~ z%8_9{W+72@!0yOFW#(#MTy(NX53@ZAA97h90eDta{JL(Y9S({i{ z2a4eo#BzSuFY{Z__mLXDk3L{Ahp_tzAabTcq+i(&E20nuh7m4NJS_v_3UkhBAa0J) zSaRq4C#5p-1`JMidHZnbuURr;t=0BKp=W+;R3BZM<%GXV*pO5(Ot5wXvz5KX%KpwT z$Ph~+!DY(ogT;};9)sD?^xp$mj8<-n?52Zc$uv)UuwG$z>E?BQLyJw((IlsT-KuAZ zFl{9UaygBm(nkq>eDvnI)Zq~!u>%(Ncp9_FMsX?p`!FitqIeC(L$qf2c@oQNWKM_% z1uZJ)paz9gAPFpYZ!8Q~HxA4_h!x|OqE6|Ozntk3tff)Ep&5!qFbb`we%7SU=u6a& zw`leg>iScNkUuP0SzRE!Ni)j{{q!w}5v{GcvJr1)(7Y6P`@Jr`Kw_;+Zj)n-MFwbD zU;{c;36m`wym1vxel`d7T$uyLHZ8FX-E?x?qo4U`fF|PHWmtm-iFDT1G2hE^>mL?=JISQsOE*|DTKx;4{v!^@&TYS}jVwPZH z=|*4*!+v5?y|me_6Ir;!9t#=p^e}d3I;5Syh&TDVHITv7)x)G6+`zOQN_Y9p!rQH^ z8ikYz2TXU}sn%BYli1ao;?{0sU})L;*$z&P3vE%12tFl5549qyOPJ*#flkXQal&1i zJyUj)k!H*751G*xbL85hA2_oS zP^2it(`hcvfZ-~~2K0_TF>xhPr}~@VEIDSzGf#KA=6J%zIaSOHXOS)zSXF_vyD`cReN6E?Rgh|=G&Fo||6qXc9WjrzdCGDC z-I}MNvZYRk;&4NQl`gcAz{#e=OM!uJ$JTWf_l@hnPGe{vi?oEeXL+s1hx3-(1(r%d zTXOT|Y%4$*Y2Jf*t7Uq>h*RyNte@E67+VmYFB&HxJkdJRcaTGw5{U%7i53j7%!fg_ z)2mdyT|@`e&vv3ZNsdApg^_KJM06|5? zXnHOSY^nG_zn4+G6w?o$yPx|iDoycyR6nzUZF^vXYFIS%-&6bpSd{Y*?(i?`rqX zw10~3ohhzv@0AHk4wvWLum{e2N>T5lVNkvky|QTVo=ums6sZn_an(lqRflz+VJMnw zG56itdR0g8ZecKjRw#n!GcQC2Wico8C(bJXZx>~}i9PpaAOBs);?6mGA07WAwlFy% zpOt1(KqU+b)~u)W!$bjiWDd-WEIZo`A4tam;tA-Z_;j)tJLSwZ8ZSB-%r)jYN=Aoe zqIpn=DV1=T1X_u}(d+ZDYO;u$WI^pu`l-=On2ZO}Zz&Z*Z{G2qW7vyjJ`~FPk}X8B z1_INEm3$F$X**2Z5uTZiS?sK^zj0(W(BP;rY7@8~jZHN3ycWz9^^S1l;uu}!^SY0! z`!aW8BtwudEu;N!Snl&iT-hn11=!LD%(7Fxqg|n$05Nj#LkU83mzQ}yB^>uB)~_&o z?@~THi_F3Y<>&qi7~JdCqwa_KDB^;UYAy59JQM(KWP&{tz?VQMF=Lc3V9|pAkSUpQZ$PFy#SHJv*q~)z-U~Yz{@)m^=$8i&6CZ@AnQF93Kc~^l_$mD+#FniPxcX#3Gz?>O|5nez?7|DLM)kCG!`!SVK`Q;0_CgJIDvizPn*zfTS=hT7XjsbSsGLsT8K1KU&rfo2u zdU~P|TYp+K(D5^G5kF}p0~4h;R%h@s;sSkHI}ZzW8;6;no}7c_AY(OL*jO1GYIfQN z!-lhm;6V}IY6!qWFG?(bWaHxY@AAeTW3-=qI>R5VYo&GL>?nztg@igs>15B=2dL*9 ztRW{nf+s^9IVt8)T03lI7E~fFkt;l_tKMUU4SI2zTv~O}{C~Q3en!LO$UJ|M zwbTJZ^VzDpGya?)hHFE$lF!0oYYuQ#L7K&zEB`F^lxrZF>2Xq;LRau)XB9&T$1|Ki z8PWRC{eeP+!~aK?e|?xvmTznY0l2@m23~`d{APnTaNhBbJ*6QcIBI}k1`~k-Xvn3y z&^YsegCi)1>E0v_k2KDMN<_5@Qp0z#=>A$1G|2L))wk4bNRw+O1Nz-FpO0(k4#~F|% z6Xu|)l3V=C9}Pf+7qS%%lg#di#by}LtjQN^w)P!CGv&4`89HaqOrEp5&Mzl-fhO|=}a`Y3{M^(`|r@L1kG<$`c!9(l1{Rb*1UR<8GZ z1?cM{i=EG~M(o1~MMamxuXBCMx3B(iYF@Vate}D{gkU|=PY>ycNf!Xn(h8j zwVt4IRIfJ_m~_PMporj}AavNCppg*heF(TK2tBwns7~ejcLtPh!XdR|WIELeGgA5E z?%}*~JfFeTl$2Sroao~(XYuztwZC-wY0fL(5+_4zy)AIWY0eDPW+-1%K{X5EjUtln&NJ zBF)627&|KY%We*L%uJX-SgG0GL4)3WW{&l}2FbmwLRe0$>j?y1hfpsJdu?1D;B+}q!R`Dk&}Y7Ip%97gr1e{}I=0yf6dL z<9+SnGpIGMlb%S*kbU#7*_0EJg#)^Gg(t>^r$rs!u!K5;r=GOGKxiQRXFyc z6kR-Vzr8)QuBXHynCPRjL>xL>LSD$Ev6cF!cJNRg+81u$6qpheG-o#48MrV4l9VBo zDd6gU9qe3?_7eky$r2)fRVjr*e4!71^JI&oL&I{I@ba|6D1I#GIK5tQgQzkA@wQY5 zxRtXa&fXV*Wt~b@apxe9nua{ZY9!9z2IOa__+jf~%=-BOy72j*W^0&XH%c5aR&z+v z7L%D#u1XGM2#;^tM21%#-5q!v!a0ObZZz{-?1uQ6fi+FVC^eH{a>T|@9rBRJF4n}F zMQ02HO5LVSGOz9H`NowVRLRv_9#n02K|HDLD^OL9t09yIp(c5r8qB>SPs!k{xTJEKJ9Ts@Tv*_-$hfV6mB~ipXVzFn1<5H{9UYBM#W!Rk>8clvZ8X-R5|>71CgJ%QlXfm zSGfAe1XBxCYCkquh6<>&)CgGpd|>SEr$z zzFhsf77)&yx8l`#8f>{ug|79-()&~-CubaS7^PL-p}(T_H^>dF`qDL zjjMB1m#k_;7b|s;(fbJp<`eY#>$e7l&6Pso)(=w)XhR{1b}ZIYcJu6x zCk`>so1y6KzRIMQCyFUJSle4+yp8=gvD#5E=4~>??ntpxKc+-y;8zLfU&5hTE{z|- zxK<7Y7VpEbvp6q3@%M?tz-2fTkJ73U5QZYT_W{F_`iHqs8cnt#i3zFG#$mWR}Fc8?>E4&`Hi3NNE5; zY~3rc6*rs>ead}oo~%vUwib3`M%`8==tyC)LDJt_ZPM`nM|QH`Z|3*jko-BEZH0zF zhMJDuLjAS)i&DRPv6c`-`kfZT@f8m&6dT4eOHnQK7&@OFm?quE+_V$2>uZS4y*F4w zM8)!?snYyGL)|30l4R|p2a$4zvVxP6}y#oPqXTzD9kQm$YvomG_KTuGEEMuurjbh6;>TzE3itJX>%rm z)|2y9KO}XKWEW6m-9MJB`)WX}f9VL+BGbQj1omI>GI;It%B^phhDGx-ah1EzE`r!k z7SER66zdYMBzMcYpLb)ZE;@?8G^u`?r9R{Bj9ypd$HEvcC7K*~KAar?G&(*%$QOhy zTJu4>vFdU{gQd8z6ZFpH0mg}|r%~kALac6ezmvqZON%0ih`^{zT8xlJuftR!#z!Dw zcL1^*+96K7F?$DJ=`KPN8?4<=fAJs9g@;XQq}?0CDyS2OehX{uUJf%^w0#T4d>HzA zASu+1^u+}8A(`TNQs`sS;fpWg+(?+ueC3r}(zgNe~t=RpcQw5u$xUMPi>q z0b6wOh&7D_r#%`4)>{u1k&{~eZ4Rpcj(Nvk?w2fOT8_lgiVy&V>ZV$%>`Mt_ukrrU z495o3B9Xqq>aeRThev=)M|;V>dRf>W<1D1x9yZvYzQ(zfD65a%T$KH5mInn5Nm2o( zSmV`jvBhl@pJec+}ZQO=^S?3<`X(~Tk43+FfsUEumJc#en z3!=Oxc;?w+Ju~h!Jj!!x>kOPBbk+&&mC+L68n#)u?B+5LTg5CKkMP}+#~)Fa`{oSYc&P9K5>}n0&)9; zK=H{iEBC^pqlH8@iN-HQ#B#i9z;wd&1KR}bSy%4f;#ejd}Op7}n$+1V^ zzm;4+pA-=8Gqjg4j^k)U`|eB_KY1^Xd!We(8#@wyv~C607m&|!Sh2UaU(ME6zIgz)WF7RjQ@R=*3u~GUO7v=z)RpYxnFxn zYfI~ECG!ipxz+;Z;NH|1N*TlFx7SAS;_iRU%oLasfhQOSv`uAEx6}1nCLtKa(HK)o9HFPyMEu4 zE5@4wFPKWBWx~kRN($MBBX!lseh-}AgZ2+v&0a(lHM_@&3F!Ij`&-Yq_pcO4fyNy?`8He){teGu zXi4Eqci~RpM^(B-D2*y{+Be@*#Dz7eMEH3w4Js6msW`l>uR{R)l})#s*<3_N5PYX4 z97%Ex?TF2iGUyxFVUjloG<6Q&2Y<1{Shtrv-}y<(1xZ!otOl3~E)WG5+gaC^+d+49 zM`n_P5j`fn9RmlP4X_ax(EcMntTlUv$go8#RN0KGJm8-`1UJbQ-0_*KE_?onh3i=> zS%&G*PiNc1h+B-<%4f)E2~Tl(*^*ltcpSq*+KN`|et1GoXK`Qt5%G>xO~kOHwb*D@ z3R9LM<5)5rpNTYC0vn$>E|Y~4ipI(fN2tpMi>t-t{u-^p2wsZBtwRyaD6zAC)61V? z03OrNx??XP;7CWWr<7YT^i~qm&+#c_acwh5FB+BN#o#8a!q+vaUHDV+)m3f5#Ora0 zVD(QKE8^JHX{5Lb$Rlfv@z4Q*PSJut$+zR&RE?FD9>a*PV`#G$3j{M84_mN$g~=&^ zr&j{qRbHEw;Jr|nB{`%ue&ok1omJ6E9+??<~dxQZ*{S6{dUWxK&b8_;ljugBxIy=tr}r z5W>CMLDbjaK~y`YJp@{mTiA<#y|-qsy@P_nANPLGf>Dbqf5BQG^@?@!el*KuE&K6t z!I-a-3`IfzLY}l*-ue3+KPu|*N_Yln3JuLKpNb31K-134d~6;RyvQDAhh>(=E~Zw> z&M($t#||1{2LP7Xmtzu2)guc{?tapAG3?_x)5-Vz?#o2T!Lce@U+ec}i?sxy(8t~1 zx}g;|g9$Ha9(Y*g{E9?mA`>t#MG{aaU@jd^rS_ST+Ktf;RQd7TqBZqXilbRr3ya}r zf9sQoV>htS3S+;nl4_6Rc~oub#~o_eMikBDXE3q2>j1LZS)6qMZmYE%^JPEOg85rQ zgEeeeF(qKPoJI6FofOXUhl^Qu@l{A>Q_Cls|`pKd+iExODGmBl+26 z!8Xpag|3SW-bb5w59p_?`AFhwZ41KdIlFqwF$WluXs>NTq1v~K4#xG^9doLmeuNP< zCtznBXI587OD4Z4ano@@zy{L}0n%fcf1J4#$4$)Pw^tB~{!UczviFy07?x*AK2@S3 z1hoA<6Lug%-Y`4v1%{-YM;=k=;JXDDB1fV)PFEP3I_S^M7jJ1-sz`<@0RdpXb*p%* z&cbS>z7#3cL!mE03fCTrf#v{XOwjny0al054X|P`J(2^9AU;4yd0!pIxoW=qt8Q4U zmb!G`^q}@5MofFH55(NNZ$$j(2va~59NU#KNo)I)+2FyBc?gPI7Hrj^F}yqS^~B*^ zz#j+pMW3NI;xa?t)^hnLH#EZLQxBFL&@D>ov@hT}-S6aFIMBP)+0=$cVT zd=HPl013maHvpw@a5=U@E}_LcI2h*xnFv?fmnaqiy33%tdtBEkW24CNTPl@<`||I& zr1l>!okD+S6SLW&x3r2o2Ki97%J_+O3Knxa)Z=f!o%$8Sxh4`D92#xUQyf`D{l+sC zZKa2vSZ^$>_bkW$QhOD`oA&yyy%*LXe+VXlPETVx*dG}EiFq@lv8hB9kM1fH$Fhwusw0dg8}$%{T&CaTVB%0WfzjPTIm*@&1YJS~ zd(@c94wCF{a-?Fg_dfs#q%(-YJ7Vi%Jb;Ik(a6SUA|5&E4~;Mkp90bM)w&#`BchGq z$dU>m(|<-O@Ck1GX~nuPH~>Qq(dy7Jd5EV<7efk~QplDsSrOj=?sAOnOT7|r1i)*B|uUyTUK;ri<6rG?$n4+e(Lvg>P`gZS5rTy zwp}4)ZsZ{F97~LI`*%9?lOKgKF!`_C0x#FPP-}G4jbgNIQp7*SXhL(6n7Fl%+DOXx zj-OY)S32jOa~+@vp@paj#M2CEVwRc>!b2EP1);3|WBiB;SU%n&NJ%Mv%a zcm54sZ-2-WIN4P8d=Dr%i%_xd&cHB{2n)@AUz!XEBt ztHDDOomEtr?P_7+AA)C=Kz{BjX{SRxhJ2m2BwSVIxn$XfxmeNKB+xAbz(ctP0yx%_ zxDS4+ks-6Zi4^kU(1!a)$hlBioGUIGvSo*BlWs{sL4Sk92KH4tIuO7e=yPx_=Pvit zDRJQ+C)p?Qa1!T19@p9A*jcw2yiXh&0~2sEujq}~NRb3&dKNZG^G6UnMti3=(d&&8 z8G1i65{{<0*MC?3`}yAASTOeSOTy=S_gCuH|8h1F$L2(z&Bs(WXNz{1+q=77`*8-v zY4maNVLoyO{Bkh|~g!B3z7 zG>OMRFjj@STlDBz0~VsBM&X*@J6@$uz=X;QT>28!0#MaXY*pUI8pqJ+468z{?z9PS zGxHr7wl>IBlygb05vlA%o{QHGAm4vxQ6+Wr<8w6yqf&8 zla_zs;`bVi0+Y_4q{%r5d}PUy)3G(*UFi~0s)?w@NEWku*8yh-=A~d{`LF~bIfB$j zC{x$U32LOZ{UkP2Cl2t)rBWfAMzbEqTdf*aDgT30ZQsrFv!sI2#$hT%XUQgHg=;jQ zt~ihv&A#k1HZ7`{EtoBjYs!k(&QUqfxV4fol`cminZ46#%JWy(r5-?DEczS{q+St4 zg~}ytEmeCiUUU#0y#x;13ss?vh!upRRXRHlIV)AA6ekUSef8p~s)YK|HoD=MIL{_< z^(6|0$I9Q74X+IU{+FtVW60h5Chw3K`AL8Chhhazt&`Qas+usR71{Id*DewiFO zpT=1$B)1YQm_}x3=xa7NN384xZL^u;1ixZ75O7v4(bma~FM(-S;D#P@5!$TAoO!yk zzd3Lwex%5XghO9Ao?4~O{*O(}9Ne-Ar zKB)HQOc`?Sob_X0yn%4QeAJVGzt_c^{^S73QdV^L>|pTz!%2+yK{M=0Z_x?IJ#N@9 z7fH&qALtS5HKgYGvb<!C6Z%RxuVQqzyF@Ol3{=_h$V^Zeo#z9G8$LDE-sFi8K!F5{ zCzFWGimjTX%4`vUHCd)!nMmIT6;uO>7Cj zCBogu)<;0-&8Ve3Q}rVA>^%&az@m`P>TWbwFhh|Wr{W21abd(xnD87M6cJl)J@6m5 z0d|AVSYw<~#J3;Qju#%BA+;;#*rL@vP0mx~?Jw4gSIAOi=BKOP|k7n&GFk3x!ONNYvQ zC0505M~%fXzg&qC90>)Dlq)<{jAA)L-CJ65Ul||WMAWKjl*Kr!$i=2%rw5?^%8&?C z+&%4qgJ8uk2_dTi$|3k~3X~e>%wYHXPYwTtJ&we`S4%(5gprjsKjN4xtc=sLRB@lr z%v_+m;6A#Y@Vq&@EDvc3o`i6GwMPYk3;6C4X|4A4lnU|VaBopLmwWOB-cM8YmzjAa z#Lh^G{5=wLqi{zeIcKA2up`kKo^5g?$1FURr_qQw0)JSroJXXPce*2VJ*@9r$1IIb z>k@kSn;#^klIZvN;21Eh;bOLS^L!-Du2(3`;C0|t@DR^-<-Hf%tfzw18~;2|>X8AI zyJs5H%qMOKH%2zUcW6To+_~)zp9T`vp2c|HJL~ImWiE=M})Yw}SnHKe7k_X-)jTNs; zv3)s({s-(3j9eTTD%fNEfObP|mK=GtM2&12=RrJ7bVlssZ+{TZ54>QV-Z;>oiW7=o z3Jn8d3pQ&RJ*R)HaD*vTafhVxSy#Cxhhwsc+b_A~tS;&>OUqTVZrr!_6tuN=DF}h? za4{Kg;#*ryFYpNf?)OJe#!@Sa#IZG%R~$7`JHtk0#M|Hnf7}NJKNDJed~C{6{Oi8i z1R-{+HLL?Cqn`&F?g;>e!&J8fG21=FaOD9+q?`apv`5qy2Xn1-7eF)?^mUG(8sxO^ zy47bYQ8b^WH~LsX<`U(MSV{(@{Dc}?pN-#1M91D5{Y&rDKe;ws>fCJe)ko~c*c<{> z0J6+(7T^~%zT7Ze$4tdeY}@q+n)x5R`Mx@c2U2bxIJ~KC<(=lWy`#wDTbnAQo|)tS zG%mh2Ym!8~Fh}sBoi7TG5FzZN(y%b;5~U#d4g;a$=JOB``2^8YD48(+0Hne$LDR5k zNw!ELj7U{8PXjHY#6(&$#>bh)C9&L}t?p7$z>YzA@)nNndGQG-#S}nh9yGWNq6z&FR+$ z_8K|Wt281{4bT%JyW9dxS{;d$`_*H8RYq%+AmkfgyA%v}b9vGtg4Xv;ky^KQ#-i6B z;1IDXyEt)^zZ(~2+KsHrI%tMaUwT)=7eYND6+ZPmuW$>L7Sk2QA7@;LP%P(BuS|Cr z9A~PUPn048{R#%rojE;;bWW<2YRGZ6l`GgX$cb}{aOE5X5}1C#<`|^f@pP=xq@Yr>)YBw!bn}42XRkN9v6dWZf)}yioM?i1)?tReH%`OoTaZe&wN`vU zbKAlQUiT5a2*2Lcskq^7UZ0MY(Mo6Lmy_oi6-W3XhLve4iLV)t4p1V}j7A4Eqva79 zVY{fS(X9uo5tvC5sDDxRyEt%k(9ATE%<61NFU5_`HDp@I+LR$ww|4}4f1@@;g}rdB zOPGh(S}`EiQ6q(|$|M2E5!XFVDjJt6861=7H^b^GTFh>Xl;tihgtp>J8>BmE$WE)z zoZIntGm^8)wE*ihX!0lxR;Oj;!zZ>IQxLMvSyhfA+9>+)R~G^D{xr4a>LTj^b{@Mk z8l%R{N}eH^>_s?IZ6+{kEk0Fc!g50^eTuO?H+6@@vdKZTg?u{!t>=J&YJ+@IT4ywI z0ecQ+J;u13X)#+d$>++S9K*Gv7qA z*@xF<*ojI>BNvEw8$}?%D0K=ftWq)=m;_IFAm<_n#e`mzJD`*t2AlK-7%?9mg>2Ft z5}0BB=*AeO{xF>!$`?v?CKM=FFuN4BJc-y>`g(+ElaySQwUcCyqTY!y&!))fC_=50 zGt}HW?;2OJ3YMg;Zx^7qYa{Y{`9_Btqs2nJx! zokCOrp?Zi*-eJCp9k-ZxOsC0H<=&r9DbKY(n;>vcVfWWBQTLF|V80{^cvrWFflVw% zi{VKS(XXR)M-^d03T4iCk6p1I9%~r@&Qq>~o)SSVR z^P(LJwraNpe#@|j$&l6_j-Grl$nS2lQt_WL(W4M)s(Oq?%VzHyPqYL?3Zl?>?5YR( zGgCmV6Z3fw3@FFzhhp(T14EL&FARwr>*M0-Y@#Z~&F|_^0UN8DVtykHVVFt*iRNOQ zop8jTq>@Z>zAOdXyV($)=2gn_54QJN$cJe#^MBx+iTs{RqXu?Zwp=-#n~DF`PMvXy zc@Zf}fj9%#AxMeE?g*Q)NTZVHk3rVrp`$vJVgo$3ZSB^*;NImw*K4Od-0>!c_oS-x z>bkl=Q&|4F1zvJ6Ik|t1JO-%>iN3E#s+_Df9O=G9#M6DH`Bg5s9sY}K^S)2Fnbs9N zcdqxF(G6z%8R_E-wv6kN-5ZlYj3G4flF}@RPr=*34peW=gO9D=K6nOh&Y1r^EOq6L z!iR!AzLXb|c-nY)6@XLNGMl$rLxUp8GUdNwZboS69|F>!jYKQ^Je$aU|; zj~Edbtio7rcc-nPKb&~rNWndaX<6%_e}ghQazk+v+SzKzO!r0is_Kxnz*s(MJkxE) zgW6OTX}60`k`VP?Mu697g#yhqmo}kx9%F79DzI)?L0ipT>mr1yL<3U?kr5nwdwNvP zV}sV69+qLx?A?)r*$EQzZa+pwZbg78U&v$=$!W)uvJbRyrqVlaLqDMXfq_A@($0Ps zzKIB0axo;&2sE5po<>!MpgXGxxKxFvdKlvKr_~i>D892A`@XtjF;v3opwzB(WR$k< zA&4pGB)@3~scq=e-4UB=pMt9ne)WEvRk-6u{Lr(89S^C;ndk4TNKiWEHrJxpmDbnA z&K+RZSG%Z(7uWB>2`|^u)|k;KQYez7$f{*_Z`C)7ovqZiB0ZcWwuh0$|JvR|91p)E zFHwH4;x3_abJX~V9MhjBsra(ZrExz1Tbd42z~U=DuN;zzxDC`xnFljMXYAOk zHSd{l0g#^YxLTADal6`iyy1<3oh@2ZXD_Z1uB4BwxoF9VIUQ3@O@p0zfTu1q#XRcg zS1-|+nkTVm)ru4BFI+?&GZ&x1#Y3*s-AShBP_ij?ujiDGj9ipKMisp}${5lb8H})$ z%S2PO3g9xAF{^{|1rN0)nj@?uM&MdGVg+i|PFvDg8j})|J9b0ja$T6veu#F{$B};1 z)c$x3F)CuHclyYqD&w&4nfUFy9AB&m(tAy$it2?WLcbOi5Yr8MeC#e3^WCQWgC-?x$DFJNvruGN*bk z$|fpn3OJ>v1J9aB|MO(-{`w{Vd6VcfExK`FVz-RBRV_1%*57Vw)d?G2xjxBZ)_Qe`3}PEWoaW(%_qq1K{j!Rj>C>Lt#8E4u5(VaQKWYNbu<4ckCg?cUfXr<|)3z06?bZGfy%n*1|KAkH9=OARtrDnp$??u}S{QUy1N zAgi1o)Rs}`OVVJ02%ndOZ|-EE6F!tvr-$)7`vy#dNl16xP9K`NMFO(>>}c1rXb2~n zX-n6M2yIQ8%Wf0v*yPJ!A96t3MGyb=I2Yb2*Rg8p<4a3Vkf)TFDpr7+&zb9pB~C<0 z;PpI_QA8;`bv({O_z0osEkkrzR_8qTxKp0C;ntobIh zNF2ETKwlPw^DixIf9&q|?k(H)04WSbrPYi&dkWH?yvBH&lZJoU2axJ@S5VTPkJUWiYE{e*gnfF)#5~KV_r%6T#V{LQx~6l z#&l~pqtyfoJ&*Rf6WssJRT9GRzJJ+Q8hCC@loALbJbwE8XL{}R$zM*j!slO*LELq6 zi$N{eQ)g-BV1KP2zf8pWx3kFGOjjPb!M0}f(55NStdzh&<4Me-_1@6XVVLaTw#4eJz}vPXZse;;EWJ`=rgg)hv;UGA%lQsmK) zUr!MB;NC2kCeVHO6q!hb@~#(==`+M|o7TFvKjKXGdTY0|U({6XV<;ils@a%6?1 zUbf{?mV5zYQMd5&*A(jMR>e9p(}aEaY3gZ7$0EV`jz}b5GyDgdanKme|m5; zogH^J5N&kx*aZnpr`6bpTGZn*7fbaAto?<@>Cq6^ZY1V6iUete%T)aD3n|hHw6#wLO*XCf3yGXz z-l;tC_VwRdE#xiHEAT~yb)7bDJuJ};ZBNzvNfVkrrY4j>C*)9y+I-EMIUyg~NchVC zCuEdE=>o$gVSmBw)*dZyW81ZLlDx#VaK-DZOK^$5vh_hDGi!x7$M*OyeRWcD=5A)x~R7aB=M#~&c)L?V9L7K*YJcoxk%f6v0^*NR6<)_94oHnXZZ@y3 zt>u=x=!@X;j#S(8$GmDOV1Tiz@3glvFsIY#PVQ|MLgCL*?}O}vOK4|OK846v^Rq1_ zq-%aEXrTgg@t>vEnyEXc16XD6-VnAg1pk4m{c4`pR=}GTQii@7l#!R7VI(w1Z~`Q> zn;NvHTdJj(k_-Kd1#r=)%n?St4A-KD29(tQv{i(Pu@WVEjZ{@iweoVqD<2qNLLzaP z+Q^w}u|K-FW&UimMiuRj0pD3rf5MnsSgncW!jN$Z8SYQf0KUnjs$ZdM|FJFfe?B3% z9G@-79RaiKi106*TvO-nizEl2GLnY5)8r*{A7wb(?jB$6(I|Dr8 zD6RR_SI(@9ByjD%Mt0t6vq#nw&=ZxfLvgWz&;zz2MgR809&`{oZ%v~Vxf3szlGQ)3 znq>Lc`cptb1fpVl*t=$%?9K4tRc#q0^;TeRvPH|_SQzRsJawyBAQ~#mHbJaB=N&{eKh%rPw3{@5r@BEk z{KZHdbxm*)lykv9TOmgHkD-6vF@LR{t`1=uKHbRtCTbl@+E1( zIId#xPWoTx0HY>N`{SI`(Gm?EC#mmJk_t;6$pry}997dbn6wAb%qD_E;~s^DXG;>Q_nuM?FPXl0x%uvhdB0^?z>!s(D+L zL1rIvkJ07_Z1n{TEKm3PcWb%-`G&2!@NbmJ$jM!c9nwODuk_r-48sxstLktHtVJJ+ z!O?^TG!Bm1L~@C-a1>l50A(y&=Nb z=ULa;IrE;?>b3cVt={7^cO0W>g%TUKq=lz*l>SA~{R{0-R8Y%wxAU93t!;OcFWTx> zVvMS{(A9t}bRHaWfR#%g`&SV&YF=sAhA-OwckZycT-p;R22}-;oXuH(uNxLv@w6^H zOf1Nhmk)l}!B0NpcYfA|pZUL|Wh&@W4@?-oEDo`UwIO1!lZo`7YjJDRo45 zp!WfKcO|9u?Y_LY|xW=hACWfuc) zbrgGl^03NT?-}4grH;+pK&5+i`O=E$U^o(Lh|FtP3$#c&r_ay7$CTkY z9QR<3k@O{7QTwMWoidT8YwCK9l}X_TE*O21@nSzQHUNiYY!C%)7rWFJhn@YB?LYhZ z=PJSe&`V{kS3Vh=KtR5B;hu4e{99f)X>D*EA*!Zl8LIK}M-yZA2h O(^tJ`(K2AK{r>^{B1{(m diff --git a/search/search_index.json b/search/search_index.json index c3a95c6f5..bc3ccf98d 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Compliance-trestle (also known as trestle)","text":"

    Trestle is an ensemble of tools that enable the creation, validation, and governance of documentation artifacts for compliance needs. It leverages NIST's OSCAL as a standard data format for interchange between tools and people, and provides an opinionated approach to OSCAL adoption.

    Trestle is designed to operate as a CICD pipeline running on top of compliance artifacts in git, to provide transparency for the state of compliance across multiple stakeholders in an environment friendly to developers. Trestle passes the generated artifacts on to tools that orchestrate the enforcement, measurement, and reporting of compliance.

    It also provides tooling to manage OSCAL documents in a more human-friendly manner. By splitting large OSCAL data structures into smaller and easier to edit sub-structures, creation and maintenance of these artifacts can follow normal git workflows including peer review via pull request, versioning, releases/tagging.

    Trestle provides three separate but related functions in the compliance space:

    • Manage OSCAL documents to allow editing and manipulation while making sure the schemas are enforced
    • Transform documents from other formats to OSCAL
    • Provide support and governance to author compliance content as markdown and drawio.

    Trestle provides tooling to help orchestrate the compliance process across a number of dimensions:

    • Help manage OSCAL documents in a more human-friendly manner by expanding the large OSCAL data structures into smaller and easier to edit sub-structures while making sure the schemas are enforced.
    • Transform documents from other formats to OSCAL
    • Provide governance for markdown documents and enforce consistency of format and content based on specified templates
    • Tooling manage authoring and governance of markdown and drawio files withn a repository.
    • Support within trestle to streamline management within a managed git environment.
    • An underlying object model that supports developers interacting with OSCAL artefacts.
    "},{"location":"#important-note","title":"Important Note:","text":"

    The current version of trestle supports NIST OSCAL 1.0.0-4. There was a breaking change in OSCAL moving from version 1.0.0 to 1.0.2 mainly due to prop becoming props in AssessmentResults. As a result, the current development path of trestle requires OSCAL 1.0.4, but for those who require OSCAL 1.0.0 please use trestle version 0.37.x. That version is stable but will not have any features added, and we encourage users to move to OSCAL 1.0.4.

    OSCAL version 1.0.0 files are still handled on import but any AssessmentResults must conform to the OSCAL 1.0.4 schema, with props instead of prop. And all files created by trestle will be output as OSCAL version 1.0.4.

    "},{"location":"#why-trestle","title":"Why Trestle","text":"

    Compliance suffers from being a complex topic that is hard to articulate simply. It involves complete and accurate execution of multiple procedures across many disciplines (e.g. IT, HR, management) with periodic verification and audit of those procedures against controls.

    While it is possible to manage the description of controls and how an organisation implements them in ad hoc ways with general tools (spreadsheets, documents), this is hard to maintain for multiple accreditations and, in the IT domain at least, creates a barrier between the compliance efforts and the people doing daily work (DevOps staff).

    Trestle aims to reduce or remove this barrier by bringing the maintenance of control descriptions into the DevOps domain. The goal is to have changes to the system (for example, updates to configuration management) easily related to the controls impacted, and to enable modification of those controls as required in concert with the system changes.

    Trestle implicitly provides a core opinionated workflow driven by its pipeline to allow standardized interlocks with other compliance tooling platforms.

    "},{"location":"#machine-readable-compliance-format","title":"Machine readable compliance format","text":"

    Compliance activities at scale, whether size of estate or number of accreditations, require automation to be successful and repeatable. OSCAL as a standard allows teams to bridge between the \"Governance\" layer and operational tools.

    By building human managed artifacts into OSCAL, Trestle is not only able to validate the integrity of the artifacts that people generate - it also enables reuse and sharing of artifacts, and furthermore can provide suitable input into tools that automate operational compliance.

    "},{"location":"#supported-oscal-elements-and-extensions","title":"Supported OSCAL elements and extensions","text":"

    trestle implicitly supports all OSCAL schemas for use within the object model. The development roadmap for trestle includes adding workflow around specific elements / objects that is opinionated.

    "},{"location":"#supported-file-formats-for-oscal-objects","title":"Supported file formats for OSCAL objects.","text":"

    OSCAL supports xml, json and yaml with their metaschema tooling. Trestle natively supports only json and yaml formats at this time.

    Future roadmap anticipates that support for xml import and upstream references will be enabled. However, it is expected that full support will remain only for json and yaml.

    Users needing to import XML OSCAL artifacts are recommended to look at NIST's XML to json conversion page here.

    "},{"location":"#python-codebase-easy-installation-via-pip","title":"Python codebase, easy installation via pip","text":"

    Trestle runs on most all python platforms (e.g. Linux, Mac, Windows) and is available on PyPi so it is easily installed via pip. It is under active development and new releases are made available regularly.

    "},{"location":"#development-status","title":"Development status","text":"

    Compliance trestle is currently stable and is based on NIST OSCAL version 1.0.4, with active development continuing.

    "},{"location":"#contributing-to-trestle","title":"Contributing to Trestle","text":"

    Our project welcomes external contributions. Please consult contributing to get started.

    "},{"location":"#license-authors","title":"License & Authors","text":"

    If you would like to see the detailed LICENSE click here. Consult contributors for a list of authors and maintainers for the core team.

    # Copyright (c) 2020 IBM Corp. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n
    "},{"location":"cli/","title":"trestle CLI Overview and OSCAL Usecases","text":"

    The trestle CLI has three primary use cases:

    • Serve as tooling to generate and manipulate OSCAL files directly by an end user. The objective is to reduce the complexity of creating and editing workflows. Example commands are: trestle import, trestle create, trestle split, trestle merge.
    • Act as an automation tool that, by design, can be an integral part of a CI/CD pipeline e.g. trestle validate, trestle tasks.
    • Allow governance of markdown documents so they conform to specific style or structure requirements.

    To support each of these use cases trestle creates an opinionated directory structure to manage governed documents.

    "},{"location":"cli/#opinionated-directory-structure","title":"Opinionated directory structure","text":"

    Trestle relies on an opinionated directory structure (trestle workspace), similar to git, go, or auditree, to manage the workflow. Most trestle commands are restricted to working within an initialized directory tree.

    The directory structure setup by trestle has three major elements:

    • A .trestle hidden folder.
    • A dist folder.
    • Folders for each of the top level OSCAL models.

    The outline of the schema is below:

    .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 dist\n\u2502   \u251c\u2500\u2500 catalogs\n\u2502   \u251c\u2500\u2500 profiles\n\u2502   \u251c\u2500\u2500 component-definitions\n\u2502   \u251c\u2500\u2500 system-security-plans\n\u2502   \u251c\u2500\u2500 assessment-plans\n\u2502   \u251c\u2500\u2500 assessment-results\n\u2502   \u2514\u2500\u2500 plan-of-action-and-milestones\n\u251c\u2500\u2500 catalogs\n\u251c\u2500\u2500 profiles\n\u251c\u2500\u2500 component-definitions\n\u251c\u2500\u2500 system-security-plans\n\u251c\u2500\u2500 assessment-plans\n\u251c\u2500\u2500 assessment-results\n\u2514\u2500\u2500 plan-of-action-and-milestones\n

    .trestle directory is a special directory containing various trestle artefacts to help run various other commands. Examples include configuration files, caches and templates.

    dist directory will contain the assembled version of the top level models located on the source model directories.

    The bulk of the folder structure is used to represent each of the top level schemas or top level models such as catalogs and profiles. For each of these directories the following root structure is maintained:

    \u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 TOP_LEVEL_MODEL_PLURAL\n    \u2514\u2500\u2500 NAME_OF_MODEL_INSTANCE\n        \u2514\u2500\u2500 TOP_LEVEL_MODEL_NAME.{json,yaml,yml}\n

    which appears, for a catalog a user decides is titled nist-800-53, as:

    \u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 nist-800-53\n        \u2514\u2500\u2500 catalog.json\n

    In most of the places in the documentation we use json format for specifying model files, but they are equally applicable to yaml format also. The default format is json, and yaml is supported on best effort basis. Within one model directory the two different formats should not be mixed.

    "},{"location":"cli/#support-for-subdivided-document-structures","title":"Support for subdivided document structures","text":"

    The files constructed by OSCAL can run into tens of thousands of lines of yaml or formatted json. At this size the files become completely unmanageable for users. To combat this, trestle can trestle split a file into many smaller files and later merge those split files together.

    Directory structures such as the one below can represent OSCAL document structures. Users are strongly encourage to rely on split and merge to code these structures.

    Users can query the contents of files using trestle describe, and probe the contents more deeply using it in combination with element paths.

    .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 dist \n\u2502   \u2514\u2500\u2500 catalogs\n\u2502       \u2514\u2500\u2500 nist800-53.json \n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 nist800-53\n        \u251c\u2500\u2500 catalog.json\n        \u2514\u2500\u2500 catalog\n            \u251c\u2500\u2500 metadata.json\n            \u251c\u2500\u2500 metadata\n            \u2502   \u251c\u2500\u2500 revision-history\n            \u2502   \u2502   \u251c\u2500\u2500 00000__revision-history.json\n            \u2502   \u2502   \u251c\u2500\u2500 00001__revision-history.json\n            \u2502   \u2502   \u2514\u2500\u2500 00002__revision-history.json   \n            \u2502   \u2514\u2500\u2500 responsible-parties\n            \u2502       \u251c\u2500\u2500 creator__responsible-party.json\n            \u2502       \u2514\u2500\u2500 contact__responsible-party.json       \n            \u2514\u2500\u2500 groups\n                \u251c\u2500\u2500 00000__group.json        \n                \u251c\u2500\u2500 00000__group\n                \u2502   \u2514\u2500\u2500 controls\n                \u2502       \u251c\u2500\u2500 00000__control.json\n                \u2502       \u2514\u2500\u2500 00001__control.json\n                \u251c\u2500\u2500 00001__group.json \n                \u2514\u2500\u2500 00001__group\n                    \u2514\u2500\u2500 controls\n                        \u251c\u2500\u2500 00000__control.json\n                        \u2514\u2500\u2500 00001__control.json\n...\n
    "},{"location":"cli/#specifying-attributes-elements-within-trestle-commands","title":"Specifying attributes / elements within trestle commands.","text":"

    OSCAL models are rich and contain multiple nested data structures. Given this, a mechanism is required to address elements /attributes within an oscal object.

    This accessing method is called 'element path' and is similar to jsonPath. Commands provide element path by a -e argument where available, e.g. trestle split -f catalog.json -e 'catalog.metadata.*'. This path is used whenever specifying an attribute or model, rather than exposing trestle's underlying object model name. Users can refer to NIST's json outline to understand object names in trestle.

    "},{"location":"cli/#rules-for-element-path","title":"Rules for element path","text":"
    1. Element path is an expression of the attribute names, in json form , concatenated by a period (.).
    2. E.g. The metadata in a catalog is referred to as catalog.metadata
    3. Element paths are relative to the file.
    4. e.g. For metadata.json roles would be referred to as metadata.roles, from the catalog file that would be catalog.metadata.roles
    5. Arrays can be handled by a wild card * or a numerical index for a specific index.
    6. catalog.groups.* to refer to each group in a catalog
    7. catalog.groups.*.controls.* to refer to 'for each control under a top level group'
    8. For NIST 800-53 catalog.groups.0.controls.0.
    9. On *nix platforms if using the wildcard the element path argument should be wrapped in quotes to prevent problems with the shell interpreting the wild card before trestle can
    10. When dealing with an array based object, the array syntax may be skipped when passing a model
    11. e.g. a control could be catalog.controls.control or catalog.groups.controls.control
    12. This syntax is required as OSCAL, across the schema, has conflicting element definitions.
    "},{"location":"cli/#a-note-for-software-developers-using-trestle","title":"A note for software developers using trestle.","text":"

    Trestle provides utilities for converting from element path to trestle's python object model. The (slightly simplified) model is:

    1. Class attributes are converted from dash-case to dash_case (aka snake_case)
    2. Class names are converted from dash-case to DashCase (aka CamelCase)
    "},{"location":"cli/#trestle-version","title":"trestle version","text":"

    This command will return the current version of Trestle and OSCAL it is using.

    Running trestle version will return:

    Trestle version v2.0.0 based on OSCAL version 1.0.4

    It can also be used to retrieve the metadata version of the OSCAL object:

    \"catalog\": {\n\n\"uuid\": \"fa3f44a8-25cd-4f6a-8175-7afe647df7ed\",\n\n\"metadata\": {\n\n\"title\": \"Catalog1\",\n\n\"last-modified\": \"2023-01-11T17:04:02.840910+00:00\",\n\n\"version\": \"0.1.10\", <<< this version here\n\n\"oscal-version\": \"1.0.4\"\n\n},\n...\n
    • -t or --type - a type of the OSCAL object (can be either catalog, profile, component-definition, system-security-plan, etc)
    • -n or --name - a name of the OSCAL object

    Running trestle version -n nist -t catalog will return:

    Version of OSCAL object of nist catalog is: 1.0.0

    "},{"location":"cli/#trestle-init","title":"trestle init","text":"

    This command will create (initialize) a trestle workspace in the current directory with the necessary directory structure and trestle artefacts. This command has multiple modes that it can run in:

    • --full
    • --local
    • --govdocs

    By default trestle init will run in the --full mode.

    --full mode is meant to be used when full functionality of Trestle is used i.e. managing OSCAL models locally, govern documents or using Trestle for API purposes. dist repository will be used when trestle assemble command is used. Running trestle init --full will create the directory structure below for different artefacts:

    .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 dist\n\u2502   \u251c\u2500\u2500 catalogs\n\u2502   \u251c\u2500\u2500 profiles\n\u2502   \u251c\u2500\u2500 component-definitions\n\u2502   \u251c\u2500\u2500 system-security-plans\n\u2502   \u251c\u2500\u2500 assessment-plans\n\u2502   \u251c\u2500\u2500 assessment-results\n\u2502   \u2514\u2500\u2500 plan-of-action-and-milestones\n\u251c\u2500\u2500 catalogs\n\u251c\u2500\u2500 profiles\n\u251c\u2500\u2500 component-definitions\n\u251c\u2500\u2500 system-security-plans\n\u251c\u2500\u2500 assessment-plans\n\u251c\u2500\u2500 assessment-results\n\u2514\u2500\u2500 plan-of-action-and-milestones\n

    --local mode is meant to be used when Trestle is used to only manage OSCAL models locally. Running trestle init --local will create the directory structure below for different artefacts:

    .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 catalogs\n\u251c\u2500\u2500 profiles\n\u251c\u2500\u2500 component-definitions\n\u251c\u2500\u2500 system-security-plans\n\u251c\u2500\u2500 assessment-plans\n\u251c\u2500\u2500 assessment-results\n\u2514\u2500\u2500 plan-of-action-and-milestones\n

    --govdocs mode is meant to be used when Trestle is only used to govern documents. Running trestle init --govdocs will create the directory structure below:

    .\n\u251c\u2500\u2500 .trestle\n

    .trestle directory is a special directory containing various trestle artefacts to help run various other commands.

    dist directory will contain the merged or assembled version of the top level models located on the source model directories which are: catalogs, profiles, component-definitions, system-security-plans, assessment-plans, assessment-results and plan-of-action-and-milestones.

    Notice that trestle is a highly opinionated tool and, therefore, the names of the files and directories that are created by any of the trestle commands and subcommands MUST NOT be changed manually.

    "},{"location":"cli/#trestle-create","title":"trestle create","text":"

    This command will create a bare-bones sample file for one of the top level OSCAL models, and it can also create new elements within an existing file. For example, trestle create -t catalog -o nist800-53 will create a sample catalog file, catalog.json in the catalog subdirectory, nist800-53 as shown below:

    .\n\u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 nist800-53\n        \u2514\u2500\u2500 catalog.json\n...\n

    The -t specifies the type of the model to create, which can be one of catalog, profile, component-definition, system-security-plan, assessment-plan, assessment-results, plan-of-action-and-milestones. Each type will be created in its corresponding directory, such as catalogs, profiles, etc.

    The following additional options are supported:

    • -o or --output: specifies the name/alias of a model. It is used as the prefix for the output filename under the dist directory and for naming the source subdirectories under catalogs, profiles, component-definitions, system-security-plans, assessment-plans, assessment-results or plan-of-action-and-milestones.

    The user can edit the parts of the generated OSCAL model by modifying the sample content in those directories.

    Passing -iof or --include-optional-fields will make trestle create generate a richer model containing all optional fields until finding recursion in the model (e.g controls within control).

    In addition, trestle create can create new components within an existing file by specifying the existing file name and the corresponding element path to create within that file.

    For example,

    $TRESTLE_BASEDIR/catalogs/nist800-53$ trestle create -f ./catalog.json -e catalog.metadata.roles

    will add the following property under the metadata property for a catalog that will be written to the appropriate file under catalogs/nist800-53 directory:

    {\n\"roles\": [\n{\n\"id\": \"REPLACE_ME\",\n\"title\": \"REPLACE_ME\"\n}\n]\n}\n

    Default values for mandatory datatypes will be like below. All UUID's will be populated by default whether or not they are mandatory.

      - DateTime: <Current date-time>\n- Boolean: false\n- Integer: 0\n- String: REPLACE_ME\n- Float/Double: 0.00\n- Id field: Auto generated UUID\n

    Again, passing -iof or --include-optional-fields will make trestle create generate a richer version of the element being created, by including optional fields.

    "},{"location":"cli/#trestle-import","title":"trestle import","text":"

    This command allows users to import existing OSCAL files so that they can be managed using trestle. For example trestle import -f /local_dir/existing_catalog.json -o my_existing_catalog will import existing_catalog.json into a new folder under catalogs as shown below:

    .\n\u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 my_existing_catalog\n        \u2514\u2500\u2500 catalog.json\n...\n

    The following options are supported:

    • -f or --file: specifies the path of an existing OSCAL file or URL to a remote file.
    • -o or --output: specifies the name/alias of a model. It is used as the prefix for the output filename under the dist directory and for naming the source subdirectories under catalogs, profiles, component-definitions, system-security-plans, assessment-plans, assessment-results or plan-of-action-and-milestones.

    The --file option may be an absolute or relative path, and it may be a URL. For details on allowed formats please see the documentation for the href command. The file must be imported from outside the current trestle directory or an error will result.

    The import subcommand can determine the type of the model that is to be imported by the contents of the file. But the file name must end with an allowed json or yaml extension: .json, .yaml, .yml

    During the import process the file must pass the validate test described below for the command, validate. If the file does not pass validation a warning will be given describing the nature of the problem and the import will fail.

    Once a file has been imported it can be split into a rich tree of sub-components as shown at the top of this document. But the file must be imported first.

    "},{"location":"cli/#trestle-replicate","title":"trestle replicate","text":"

    This command allows users to replicate a certain OSCAL model (file and directory structure). For example trestle replicate catalog -n cat1 -o cat11 will replicate the Catalog cat1 into cat11 directory. It can also regenerate all the UUIDs as required.

    "},{"location":"cli/#trestle-split","title":"trestle split","text":"

    This command allows users to further decompose a trestle model into additional subcomponents.

    The following options are currently supported:

    • -f or --file: this is optional and specifies the file path of the json/yaml file containing the elements that will be split.
    • -e or --elements: specifies the model subcomponent element(s) (JSON/YAML property path) that is/are going to be split. Multiple elements can be specified at once using a comma-separated value, e.g -e 'catalog.metadata,catalog.groups'. Make sure to include the quotes that enclose the comma-separated paths.

    If the element is of JSON/YAML type array list and you want trestle to create a separate subcomponent file per array item, the element needs to be suffixed with .*, e.g. -e 'catalog.groups.*'. If the suffix is not specified, split will place all array items in only one separate subcomponent file, e.g. 'groups.json'. Again, make sure to include the quotes around the elements.

    If you just want to split a file into all its constituent parts and the file does not contain a simple list of objects, you can still use * and the file will be split into all its non-trivial elements. Thus if you split a catalog with -e catalog.* the result will be a new directory, catalog, containing files representing the large items, back-matter.json, groups.json and metadata.json, but there will still be a catalog.json file containing just the catalog's uuid. Small items such as strings and dates cannot be split off and will remain in the original model file that is being split.

    Here are some examples. Starting with a single catalog file, my_catalog/catalog.json, if you do trestle split -f catalog.json -e 'catalog.*' you end up with:

    catalogs\n \u2517 my_catalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

    If you then split roles out of metadata as a single file containing a list of roles, trestle split -f catalog/metadata.json -e 'metadata.roles' you would end up with:

    catalogs\n \u2517 my_catalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2517 roles.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

    If instead you had specified -e 'metadata.roles.*' you would get:

    my_catalog\n \u2523 catalog\n \u2503 \u2523 metadata\n \u2503 \u2503 \u2517 roles\n \u2503 \u2503 \u2503 \u2523 00000__role.json\n \u2503 \u2503 \u2503 \u2517 00001__role.json\n \u2503 \u2523 back-matter.json\n \u2503 \u2523 groups.json\n \u2503 \u2517 metadata.json\n \u2517 catalog.json\n

    You can see there is no roles.json file anymore and instead there is a subdirectory, roles containing a list of files, one for each role.

    If the -f or --file option is not specified, the file to split will be determined from the elements specified, in the context of the current working directory. The current directory must be within a specific model (e.g. catalog or profile), and the element paths must either be absolute (e.g. catalog.metadata.roles) or relative to the current working directory. For example, if you are in catalogs/mycat/catalog/groups and you want to split the file 00000__group.json, you must use -f to specify the filename, and the element path can either be absolute, as catalog.group.*, or you can set the current working directory to where the file is and use element path group.*. This makes it easier to specify splits when deep in a directory structure.

    Every subdirectory in a trestle directory model should have a corresponding .json or .yaml file with the same name, except when that subdirectory corresponds to a list of items, such as catalog.groups. When those subcomponents are split/expanded each file or subdirectory under them represents an item of the collection. Because of that, if a corresponding groups.json | groups.yaml file were to exist, its contents would just be an empty representation of that collection and the user would need to be careful never to edit that file. Therefore, we decided not to create that corresponding file in those cases. Following the same logic, another exception is when all the fields from a .json | .yaml file are split, leaving the original file as an empty object. In that case, the file would be deleted as well.

    To inspect a file to see what elements can be split from it, use the describe command described below. It is also useful for inspection of files created by the split operation.

    "},{"location":"cli/#trestle-merge","title":"trestle merge","text":"

    The trestle merge command is the reversal of trestle split. This command allows users to reverse the decomposition of a trestle model by aggregating subcomponents scattered across multiple files or directories into the parent JSON/YAML file. To merge a model, you have to first change working directory to the root model component directory that you want to merge a sub-component model into. The following option is required:

    • -e or --elements: specifies the properties (JSON/YAML path) that will be merged, relative to the current working directory. This must contain at least 2 elements, where the last element is the model/sub-component to be merged into the second from last component.

    For example, in the command trestle merge -e 'catalog.metadata', executed in the same directory where catalog.json or the split catalog directory exists, the property metadata from metadata.json would be moved/merged into catalog.json. If the metadata model has already been split into smaller sub-component models previously, those smaller sub-components are first recusively merged into metadata, before merging metadata subcomponent into catalog. To specify merging every sub-component split from a component, .* can be used. For example, trestle merge -e 'catalog.*' command, issued from the directory where catalog.json orcatalog directory exists, will merge every single sub-component of that catalog back into the catalog.json.

    "},{"location":"cli/#trestle-describe","title":"trestle describe","text":"

    This command lets users inspect model files to explore contents using an optional element path. The command can work well in concert with split to show what each file contains, and probe within the contents to determine sub-components that can be extracted as separate files.

    Unlike split, describe only describes the contents of a single item, so the element path may not contain wildcards (*) or commas.

    For example, if a catalog file has been imported to catalogs/my_catalog/catalog.json then the commmand, trestle describe -f catalog.json might yield:

    #Model file catalog.json is of type catalog.Catalog and contains\nuuid: 613fca2d-704a-42e7-8e2b-b206fb92b456\nmetadata: common.Metadata\nparams: None\ncontrols: None\ngroups: list of 20 items of type catalog.Group\nback_matter: common.BackMatter\n

    Note that contents are listed even when they are empty (and therefore optional) so the full potential contents can be seen. Also note that if an item corresponds to a list of elements, the number and type of elements is provided. Finally, if an item is a simple string such as id, uuid or title, the string is shown directly up to a maximum of 100 characters. If the string is clipped it will be indicated by [truncated] at the end of the string.

    An element path can be specified to probe the contents, as in trestle describe -f catalog.json -e 'catalog.metadata.roles'. A possible response is:

    Model file catalog.json at element path catalog.metadata.roles is a list of 2 items of type common.Role\n

    You can also query individual elements, and elements of an element, e.g. trestle describe -f catalog.json -e 'catalog.groups.5.controls.3'

    # Model file catalog.json at element path catalog.groups.5.controls.3 is of type catalog.Control and contains:\nid: cp-4\nclass_: SP800-53\ntitle: Contingency Plan Testing\nparams: list of 2 items of type common.Parameter\nprops: list of 2 items of type common.Property\nlinks: list of 14 items of type common.Link\nparts: list of 2 items of type common.Part\ncontrols: list of 5 items of type catalog.Control\n

    (Note that the numbering starts at 0, so the .3 corresponds to the 4th element.)

    In all output from describe the type of the item shown corresponds to the python file and class of the corresponding OSCAL model in trestle.

    If you split items off a model so they end up in a subdirectory, the original file is referred to as a \"stripped\" model, with parts of it stripped off and only some elements remaining. For example, if you do trestle split -f catalog.json -e 'catalog.metadata' it will split off metadata from the original catalog.json file and place it in catalog/metadata.json. If you then do trestle describe -f catalog.json on the new file, it will say something like:

    # Model file catalog.json is of type stripped.Catalog and contains:\nuuid: 613fca2d-704a-42e7-8e2b-b206fb92b456\nparams: None\ncontrols: None\ngroups: list of 20 items of type catalog.Group\nback_matter: common.BackMatter\n

    Note that the type of the file is now stripped.Catalog and it no longer contains metadata. Even though metadata is no longer in the original .json file, trestle is still aware it is present in the model since it is properly placed as its own file in the subdirectory, catalog.

    "},{"location":"cli/#trestle-partial-object-validate","title":"trestle partial-object-validate","text":"

    OSCAL objects may be extremely large. Some systems may only be able to produce partial OSCAL objects. For example, the tanium-result-to-oscal-ar task produces the results attribute of an assessment-results object.

    trestle partial-object-validate allows the validation of any sub-element/attribute using element path.

    Using the example above trestle partial-object-validate -f results.json -e assessment-results.results.

    The file is not required to be in the trestle directory or required to be a specific file name.

    "},{"location":"cli/#example-valid-element-paths","title":"Example valid element-paths","text":"

    All element paths must be absolute e.g.: catalog.metadata catalog catalog.groups catalog.groups.group.controls.control.controls.control Remembering in the end you only care about the end type. So in this scenario catalog.groups.group.controls.control.controls.control is equivalent to catalog.controls.control.

    "},{"location":"cli/#trestle-href","title":"trestle href","text":"

    This command changes the href of an Import in a profile and is needed when generating an SSP (system security plan) with the author tool, ssp-generate. The Imports in a profile are used to load associated catalogs of controls and profiles, and must be available at the corresponding href uri. If an imported catalog is in the trestle directory then the href should be changed with a command of the form:

    trestle href -n my_profile -hr trestle://catalogs/my_catalog/catalog.json\n

    Similarly, if the item imported is a profile, a corresponding href should point to a json file in the profiles directory.

    Note that catalogs or profiles in the trestle directory are indicated by the trestle:// prefix, followed by the path from the top level models directory to the actual catalog file. The profile itself, which is having its imports modified, is just indicated by its name with the -n option.

    If the profile has more than one import, you can display the corresponding hrefs with:

    trestle href -n my_profile\n

    This will give a numbered list of the hrefs. You can then change them individually by providing the corresponding item number:

    trestle href -n my_profile -i 1 -hr trestle://catalogs/my_catalog/catalog.json\n

    This will change the href indexed as 1 when the list was displayed. The href's are indexed starting from 0.

    The trestle href command can also be used to change the value back to the intended one prior to distribution of the profile.

    The provided href can be of form trestle://, https://, sftp://, or file:///. If file:/// is used, the path provided must be absolute - and on Windows it must include the drive letter followed by a slash. The only time a relative path is allowed is with the trestle:// heading.

    A username and password may be embedded in the url for https://, and a CA certificate path will be searched from environment variables REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE in that order.

    Authorization for sftp:// access relies on the user's private key being either active via ssh-agent or supplied via the environment variable SSH_KEY. In the latter case it must not require a passphrase prompt.

    "},{"location":"cli/#trestle-assemble","title":"trestle assemble","text":"

    This command assembles all contents (files and directories) representing a specific model into a single OSCAL file located under dist folder. For example,

    $TRESTLE_BASEDIR$ trestle assemble catalog -n nist800-53

    will traverse the catalogs/nist800-53 directory and its children and combine all data into a OSCAL file that will be written to dist/catalogs/nist800-53.json. Note that the parts of catalog nist800-53 can be written in either YAML/JSON (e.g. based on the file extension), however, the output will be generated as YAML/JSON as desired. Trestle will infer the content type from the file extension and create the model representation appropriately in memory and then output in the desired format. Trestle assemble will also validate content as it assembles the files and make sure the contents are syntactically correct.

    "},{"location":"cli/#trestle-remove","title":"trestle remove","text":"

    The trestle remove command is the reversal of trestle create -f filename.json -e element_path, as it will remove the corresponding element from the specified file.

    "},{"location":"cli/#trestle-validate","title":"trestle validate","text":"

    Trestle validate checks the integrity of one or more OSCAL files in a number of ways.

    validate returns a non-zero return code if there is any validation problem detected in a file.

    The current list of validation modes that get checked internally are:

    Mode Purpose duplicates Detect whether disallowed duplicate uuid's are present oscal_version Confirm that the oscal version of the file is supported refs Confirm that all references in responsible parties are found in roles catalog Confirm all parameter ids in a catalog are unique links Confirm referenced resources are 1:1 with resources in backmatter

    You can validate a single model file by specifying its full path:

    trestle validate -f catalogs/my_cat/catalog.json

    or by specifying its model name and type:

    trestle validate -t catalog -n my_cat

    In addition to validating a single file you can validate all files of a given type with the -t option and no file name:

    trestle validate -t catalog

    And you can validate all models with the -a option:

    trestle validate -a

    Note that when you Import a file it will perform a full validation on it first, and if it does not pass validation the file cannot be imported.

    By default validate will display warning messages and a message indicating the file is valid, but you can suppress those messages with the -q --quiet option.

    The links validator is special because it always returns success that the file is valid - but it will list any inconsistencies it finds between the references to links, and corresponding links in the backmatter.

    "},{"location":"cli/#trestle-tasks","title":"trestle tasks","text":"

    Open Shift Compliance Operator and Tanium are supported as 3rd party tools.

    "},{"location":"cli/#trestle-task-xccdf-result-to-oscal-ar","title":"trestle task xccdf-result-to-oscal-ar","text":"

    The trestle task xccdf-result-to-oscal-ar command facilitates transformation of XCCDF results, e.g. OpenShift Compliance Operator (OSCO) scan results, .yaml files into OSCAL partial results .json files. Specify required config parameters to indicate the location of the input and the output. Specify optional config parameters to indicate the name of the oscal-metadata.yaml file, if any, and whether overwriting of existing output is permitted.

    Example command invocation:

    $TRESTLE_BASEDIR$ trestle task xccdf-result-to-oscal-ar -c /home/user/task.config

    Example config:

    /home/user/task.config

    [task.xccdf-result-to-oscal-ar]\n\ninput-dir =  /home/user/git/evidence/xccdf/input\noutput-dir = /home/user/git/evidence/oscal/output\noscal-metadata = oscal-metadata.yaml\noutput-overwrite = true\n

    input

    Example input directory contents listing:

    /home/user/git/evidence/xccdf/input

    -rw-rw-r--. 1 user user  3832 Feb  2 09:36 oscal-metadata.yaml\n-rw-rw-r--. 1 user user 49132 Feb  2 06:12 ssg-ocp4-ds-cis-111.222.333.444-pod.yaml\n-rw-rw-r--. 1 user user 52747 Feb  2 06:41 ssg-ocp4-ds-cis-111.222.333.555-pod.yaml\n

    Example input OSCO scan result file contents (snippet):

    ssg-ocp4-ds-cis-111.222.333.444-pod.yaml

    display sample
    apiVersion: v1\ndata:\nexit-code: '2'\nresults: |\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<TestResult xmlns=\"https://checklists.nist.gov/xccdf/1.2\" \nid=\"xccdf_org.open-scap_testresult_xccdf_org.ssgproject.content_profile_cis\"\nstart-time=\"2020-08-03T02:26:26+00:00\" end-time=\"2020-08-03T02:26:26+00:00\"\nversion=\"0.1.52\"\ntest-system=\"cpe:/a:redhat:openscap:1.3.3\">\n<benchmark href=\"/content/ssg-ocp4-ds.xml\" id=\"xccdf_org.ssgproject.content_benchmark_OCP-4\"/>\n<title>OSCAP Scan Result</title>\n<profile idref=\"xccdf_org.ssgproject.content_profile_cis\"/>\n<target>kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp</target>\n<target-facts>\n<fact name=\"urn:xccdf:fact:identifier\" type=\"string\">chroot:///host</fact>\n<fact name=\"urn:xccdf:fact:scanner:name\" type=\"string\">OpenSCAP</fact>\n<fact name=\"urn:xccdf:fact:scanner:version\" type=\"string\">1.3.3</fact>\n</target-facts>\n<target-id-ref system=\"https://scap.nist.gov/schema/asset-identification/1.1\" name=\"asset0\" href=\"\"/>\n<platform idref=\"cpe:/a:redhat:openshift_container_platform:4.1\"/>\n<platform idref=\"cpe:/a:machine\"/>\n<set-value idref=\"xccdf_org.ssgproject.content_value_ocp_data_root\">/kubernetes-api-resources</set-value>\n<set-value idref=\"xccdf_org.ssgproject.content_value_var_kube_authorization_mode\">Webhook</set-value>\n<set-value idref=\"xccdf_org.ssgproject.content_value_var_streaming_connection_timeouts\">5m</set-value>\n<rule-result idref=\"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\" time=\"2020-08-03T02:26:26+00:00\" severity=\"medium\" weight=\"1.000000\">\n<result>notselected</result>\n<ident system=\"https://nvd.nist.gov/cce/index.cfm\">CCE-84209-6</ident>\n</rule-result>\n<rule-result idref=\"xccdf_org.ssgproject.content_rule_accounts_restrict_service_account_tokens\" time=\"2020-08-03T02:26:26+00:00\" severity=\"medium\" weight=\"1.000000\">\n<result>notchecked</result>\n<message severity=\"info\">No candidate or applicable check found.</message>\n</rule-result>\n<rule-result idref=\"xccdf_org.ssgproject.content_rule_accounts_unique_service_account\" time=\"2020-08-03T02:26:26+00:00\" severity=\"medium\" weight=\"1.000000\">\n<result>notchecked</result>\n<message severity=\"info\">No candidate or applicable check found.</message>\n</rule-result>\n\n...\n\n</TestResult>\nkind: ConfigMap\nmetadata:\nannotations:\ncompliance-remediations/processed: ''\ncompliance.openshift.io/scan-error-msg: ''\ncompliance.openshift.io/scan-result: NON-COMPLIANT\nopenscap-scan-result/node: 111.222.333.444\ncreationTimestamp: '2020-08-03T02:26:34Z'\nlabels:\ncompliance-scan: ssg-ocp4-ds-cis\nname: ssg-ocp4-ds-cis-111.222.333.444-pod\nnamespace: openshift-compliance\nresourceVersion: '22693328'\nselfLink: /api/v1/namespaces/openshift-compliance/configmaps/ssg-ocp4-ds-cis-111.222.333.444-pod\nuid: 1da3ea81-0a25-4512-ad86-7ac360246b5d\n

    Example input OSCAL metadata file contents:

    oscal-metadata.yaml

    display sample
    ssg-ocp4-ds-cis-111.222.333.444-pod:\nlocker: https://github.mycorp.com/degenaro/evidence-locker\nnamespace: xccdf\nbenchmark: CIS Kubernetes Benchmark\nsubject-references:\ncomponent:\nuuid-ref: 56666738-0f9a-4e38-9aac-c0fad00a5821\ntype: component\ntitle: Red Hat OpenShift Kubernetes\ninventory-item:\nuuid-ref: 46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\ntype: inventory-item\ntitle: Pod\nproperties:\ntarget: kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\ntarget-ip: 111.222.333.444\ncluster-name: ROKS-OpenSCAP-1\ncluster-type: openshift\ncluster-region: us-south\n\nssg-rhel7-ds-cis-111.222.333.444-pod:\nlocker: https://github.mycorp.com/degenaro/evidence-locker\nnamespace: xccdf\nbenchmark: CIS Kubernetes Benchmark\nsubject-references:\ncomponent:\nuuid-ref: 89cfe7a7-ce6b-4699-aa7b-2f5739c72001\ntype: component\ntitle: RedHat Enterprise Linux 7.8\ninventory-item:\nuuid-ref: 46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\ntype: inventory-item\ntitle: VM\nproperties:\ntarget: kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\ntarget-ip: 111.222.333.444\ncluster-name: ROKS-OpenSCAP-1\ncluster-type: openshift\ncluster-region: us-south\n

    metadata format

    The oscal-metadata.yaml file comprises one or more mappings. Below is shown the format of a single mapping. The items in angle brackets are to be replaced with desired values for augmenting the produced OSCAL.

    The mapping whose name matches the [metadata][name] in the evidence for the corresponding embedded XML, if any, will be used for augmenting the produced OSCAL.

    name:\nlocker: <locker>\nnamespace: <namespace>\nbenchmark: <benchmark>\nsubject-references:\ncomponent:\nuuid-ref: <uuid-ref-component>\ntype: <component-type>\ntitle: <component-title>\ninventory-item:\nuuid-ref: <uuid-ref-inventory-item>\ntype: <inventory-item-type>\ntitle: <inventory-item-title>\nproperties:\ntarget: <target>\ncluster-name: <cluster-name>\ncluster-type: <cluster-type>\ncluster-region: <cluster-region>\n

    output

    Example output directory contents listing:

    /home/user/git/evidence/oscal/output

    -rw-rw-r--. 1 user user 49132 Feb  3 10:59 ssg-ocp4-ds-cis-111.222.333.444-pod.json\n-rw-rw-r--. 1 user user 52747 Feb  3 10:59 ssg-ocp4-ds-cis-111.222.333.555-pod.json\n

    Example output OSCAL Observations file contents (snippet):

    ssg-ocp4-ds-cis-111.222.333.444-pod.json

    display sample
    {\n\"observations\": [\n{\n\"uuid\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"title\": \"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\",\n\"description\": \"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://osco\",\n\"class\": \"source\",\n\"value\": \"CIS Kubernetes Benchmark\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"type\": \"component\",\n\"title\": \"Red Hat OpenShift Kubernetes\"\n},\n{\n\"uuid-ref\": \"46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\",\n\"type\": \"inventory-item\",\n\"title\": \"Pod\",\n\"props\": [\n{\n\"name\": \"target\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\"\n},\n{\n\"name\": \"target-ip\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"111.222.333.444\"\n},\n{\n\"name\": \"cluster-name\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"ROKS-OpenSCAP-1\"\n},\n{\n\"name\": \"cluster-type\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"openshift\"\n},\n{\n\"name\": \"cluster-region\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"us-south\"\n}\n]\n}\n],\n\"relevant-evidence\": [\n{\n\"href\": \"https://github.mycorp.com/degenaro/evidence-locker\",\n\"description\": \"Evidence location.\",\n\"props\": [\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"id\",\n\"value\": \"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\"\n},\n{\n\"name\": \"time\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"timestamp\",\n\"value\": \"2020-08-03T02:26:26+00:00\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"result\",\n\"value\": \"notselected\"\n}\n]\n}\n]\n}\n]\n}\n
    "},{"location":"cli/#trestle-task-tanium-result-to-oscal-ar","title":"trestle task tanium-result-to-oscal-ar","text":"

    The trestle task tanium-result-to-oscal-ar command facilitates transformation of Tanuim reports, each input file comprising individual lines consumable as json, into OSCAL partial results .json files. Specify required config parameters to indicate the location of the input and the output. Specify optional config parameter output-overwrite to indicate whether overwriting of existing output is permitted. Specify optional config parameter timestamp as ISO 8601 formated string (e.g., 2021-02-24T19:31:13+00:00) to override the timestamp attached to each Observation.

    Example command invocation:

    $TRESTLE_BASEDIR$ trestle task tanium-result-to-oscal-ar -c /home/user/task.config

    Example config:

    /home/user/task.config

    [task.tanium-result-to-oscal-ar]\n\ninput-dir =  /home/user/git/compliance/tanium/input\noutput-dir = /home/user/git/compliance/oscal/output\noutput-overwrite = true\n

    input

    Example input directory contents listing:

    /home/user/git/compliance/tanium/input

    -rw-rw-r--. 1 degenaro degenaro 1830 Mar  7 08:23 Tanium.comply-nist-results\n

    Tanium.comply-nist-results

    display sample
    {\n\"IP Address\": \"fe80::3cd5:564b:940e:49ab\",\n\"Computer Name\": \"cmp-wn-2106.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"Result\": \"pass\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
    {\n\"IP Address\": \"10.8.69.11\",\n\"Computer Name\": \"\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.2_L1_Ensure_Maximum_password_age_is_set_to_60_or_fewer_days_but_not_0\",\n\"Result\": \"pass\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
    {\n\"IP Address\": \"10.8.69.11\",\n\"Computer Name\": \"cmp-wn-2106.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.3_L1_Ensure_Minimum_password_age_is_set_to_1_or_more_days\",\n\"Result\": \"fail\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
    {\n\"IP Address\": \"10.8.69.11\",\n\"Computer Name\": \"cmp-wn-2106.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.4_L1_Ensure_Minimum_password_length_is_set_to_14_or_more_characters\",\n\"Result\": \"pass\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n

    output

    Example output directory contents listing:

    /home/user/git/compliance/oscal/output

    -rw-rw-r--. 1 degenaro degenaro 6479 Mar  7 08:25 Tanium.oscal.json\n

    Tanium.oscal.json

    display sample
    {\n\"results\": [\n{\n\"uuid\": \"0ed0791e-5454-4d07-919f-15a0d806a5a8\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-04-13T00:16:20.000+00:00\",\n\"local-definitions\": {\n\"inventory-items\": [\n{\n\"uuid\": \"da8b87f6-2068-415f-94bb-e14e31b4f5c2\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"computer-name\",\n\"ns\": \"dns://tanium\",\n\"value\": \"cmp-wn-2106.demo.tanium.local\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"computer-ip\",\n\"ns\": \"dns://tanium\",\n\"value\": \"fe80::3cd5:564b:940e:49ab\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"value\": \"Windows 10\",\n\"class\": \" inventory-item\"\n}\n]\n},\n{\n\"uuid\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"computer-name\",\n\"ns\": \"dns://tanium\",\n\"value\": \"\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"computer-ip\",\n\"ns\": \"dns://tanium\",\n\"value\": \"10.8.69.11\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"value\": \"Windows 10\",\n\"class\": \" inventory-item\"\n}\n]\n}\n]\n},\n\"reviewed-controls\": {\n\"control-selections\": [\n{}\n]\n},\n\"observations\": [\n{\n\"uuid\": \"b3250b66-fe6f-4ac0-be99-cb4ff093dc31\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"pass\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"da8b87f6-2068-415f-94bb-e14e31b4f5c2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n},\n{\n\"uuid\": \"5ae9c133-c32d-44c5-b52e-5af4513cb94a\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.2_L1_Ensure_Maximum_password_age_is_set_to_60_or_fewer_days_but_not_0\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.2_L1_Ensure_Maximum_password_age_is_set_to_60_or_fewer_days_but_not_0\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"pass\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n},\n{\n\"uuid\": \"8d021edc-176e-4373-a3c4-a19e954c1e4d\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.3_L1_Ensure_Minimum_password_age_is_set_to_1_or_more_days\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.3_L1_Ensure_Minimum_password_age_is_set_to_1_or_more_days\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"fail\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n},\n{\n\"uuid\": \"36aa7551-d047-4f4a-9853-6ac63cfc9e48\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.4_L1_Ensure_Minimum_password_length_is_set_to_14_or_more_characters\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.4_L1_Ensure_Minimum_password_length_is_set_to_14_or_more_characters\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"pass\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n}\n],\n\"findings\": [\n{\n\"uuid\": \"ba4e264f-0aee-4ead-9ee3-6161c5cc4ecb\",\n\"title\": \"800-53: IA-5\",\n\"description\": \"800-53: IA-5\",\n\"target\": {\n\"type\": \"objective-id\",\n\"id-ref\": \"800-53: IA-5\",\n\"props\": [\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"value\": \"NIST 800-53\",\n\"class\": \"source\"\n},\n{\n\"name\": \"id-ref\",\n\"ns\": \"dns://tanium\",\n\"value\": \"800-53: IA-5\",\n\"class\": \"source\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"FAIL\",\n\"class\": \"STRVALUE\"\n}\n],\n\"status\": \"not-satisfied\"\n},\n\"related-observations\": [\n{\n\"observation-uuid\": \"b3250b66-fe6f-4ac0-be99-cb4ff093dc31\"\n},\n{\n\"observation-uuid\": \"5ae9c133-c32d-44c5-b52e-5af4513cb94a\"\n},\n{\n\"observation-uuid\": \"8d021edc-176e-4373-a3c4-a19e954c1e4d\"\n},\n{\n\"observation-uuid\": \"36aa7551-d047-4f4a-9853-6ac63cfc9e48\"\n}\n]\n}\n]\n}\n]\n}\n
    "},{"location":"cli/#trestle-task-xlsx-to-oscal-cd","title":"trestle task xlsx-to-oscal-cd","text":"

    The trestle task xlsx-to-oscal-cd command facilitates transformation of an excel spreadsheet into an OSCAL component-definition.json file. Specify in the config:

    • location of catalog file
    • location of spreadsheet file
    • work sheet name in the spreadsheet file
    • output directory to write the component-definition.json file
    • whether or not to overwrite an existing component-definition.json file
    • the organization name
    • the organization remarks
    • the namespace
    • comma separated mappings from name to class
    • the catalog URL
    • the catalog title

      Example command invocation:

      $TRESTLE_BASEDIR$ trestle task xlsx-to-oscal-cd -c /home/user/task-xlsx-to-oscal-cd.config

      Example config:

      /home/user/task-xlsx-to-oscal-cd.config

      [task.xlsx-to-oscal-cd]\n\ncatalog-file = nist-content/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json\nspread-sheet-file = /home/user/compliance/data/spread-sheet/good.xlsx\nwork-sheet-name = example_best_practices_controls\noutput-dir = /home/user/compliance/data/tasks/xlsx/output\noutput-overwrite = true\n\norg-name = International Business Machines\norg-remarks = IBM\nnamespace = https://oscal-compass.github.io/compliance-trestle/schemas/oscal/cd/ibm-cloud\nproperty-name-to-class = goal_name_id:scc_goal_name_id, goal_version:scc_goal_version\ncatalog-url = https://github.com/usnistgov/oscal-content/blob/master/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json\ncatalog-title = NIST Special Publication 800-53 Revision 4\n

      catalog-file

      Example catalog-file:

      nist-content/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json

      spread-sheet-file

      Example spread-sheet-file:

      /home/user/compliance/data/spread-sheet/good.xlsx

      output

      Example component-definition.json:

      /home/user/compliance/data/tasks/xlsx/output/component-definition.json

      "},{"location":"cli/#spreadsheet-to-component-definition-mapping","title":"spreadsheet to component definition mapping","text":"display mapping table spreadsheet column name component definition path comments ControlId
      • implemented_requirement.property[name='goal_name_id'].value
        • only used if column 'goal_name_id' is empty ControlText
          • implemented_requirement.property[name='goal_name_id'].remarks
            • transformation code replaces \"Check whether\" with \"Ensure\" in text Nist Mappings
              • implemented_requirement.description
                • heading may span multiple columns
                • one value expected per column
                • each entry is separated into control + statements (if any) ResourceTitle
                  • component.title
                  • component.description
                  • component.control-implementation.description + {text}
                    goal_name_id
                    • implemented_requirement.property[name='goal_name_id'].value
                      Version
                      • implemented_requirement.property[name='goal_version'].value
                        • Value from spreadsheet is not currently used.
                        • Value '1.0' is hard coded. Parameter [optional parameter]
                          • implemented_requirement.set_parameter.param_id
                            • The expected text is in two parts separated by '\\n'.
                            • The text following the '\\n' is the value used. Values [alternatives]
                              • implemented_requirement.set_parameter.values
                                • The expected text is of the following format:
                                • v0, [v1, v2...]
                                • The value v0 is used."},{"location":"cli/#trestle-task-xlsx-to-oscal-profile","title":"trestle task xlsx-to-oscal-profile","text":"

                                  The trestle task xlsx-to-oscal-profile command facilitates transformation of an excel spreadsheet into an OSCAL profile.json file. Specify in the config:

                                  • the href URL of the spreadsheet
                                  • file system location of spreadsheet file
                                  • work sheet name in the spreadsheet file
                                  • output directory to write the profile.json file
                                  • whether or not to overwrite an existing profile.json file
                                  • the profile title

                                    Example command invocation:

                                    $TRESTLE_BASEDIR$ trestle task xlsx-to-oscal-profile -c /home/user/task-xlsx-to-oscal-profile.config

                                    Example config:

                                    /home/user/task-xlsx-to-oscal-profile.config

                                    [task.xlsx-to-oscal-profile]\n\nspread-sheet-url = https://github.mycorp.com/spread-sheets/good.xlsx\nspread-sheet-file = /home/user/compliance/data/spread-sheet/good.xlsx\nwork-sheet-name = example_best_practices_controls\noutput-dir = /home/user/compliance/data/tasks/xlsx/output\noutput-overwrite = true\n\nprofile-title = IBM Best Practices SCC GOALS\n

                                    spread-sheet-file

                                    Example spread-sheet-file:

                                    /home/user/compliance/data/spread-sheet/good.xlsx

                                    output

                                    Example profile.json:

                                    /home/user/compliance/data/tasks/xlsx/output/profile.json

                                    "},{"location":"demonstrations-content/","title":"Trestle demonstration projects and content","text":"

                                    Trestle has a number of demonstrations setup in the oscal-compass/compliance-trestle-demos repository which is intended to be a single point of call for demonstrations and content.

                                    If you are interested in contributing a demonstration / content open a PR to the demonstration repo and a PR to this page.

                                    Demonstrations, where practical, should include instructions on how they were created.

                                    "},{"location":"demonstrations-content/#current-demonstrations","title":"Current demonstrations","text":""},{"location":"demonstrations-content/#simple-sdk-examples","title":"Simple sdk examples.","text":"

                                    This folder contains a number of small examples for using the trestle OSCAL sdks.

                                    "},{"location":"demonstrations-content/#arc42-architectural-template-enforcement-using-trestle-author","title":"arc42 architectural template enforcement using trestle author.","text":"

                                    arc42 have created a set of open-source architecture documentation templates. This demonstration uses trestle author to enforce use of the (modified) arc42 templates.

                                    "},{"location":"demonstrations-content/#trestle-flask-microservice-demonstration","title":"Trestle flask microservice demonstration.","text":"

                                    trestle uses a python library called pydantic to form the underlying OSCAL object models. flask-pydantic introduces a mechanism which integrates pydantic models into flask, providing automated user input validation in one line of code. This demo accepts a catalog as a POSTed object, throwing errors if the catalog does not meet the schema, and returns the catalog in the response. Find the demonstration here.

                                    "},{"location":"demonstrations-content/#creating-a-cis-controls-catalog-from-an-excel-spreadsheet","title":"Creating a CIS controls catalog from an excel spreadsheet.","text":"

                                    The Centre for Internet Security (CIS) produce a number of cross industry standards for IT security including their platform specific benchmarks and a suite of controls. This demo converts a spreadsheet of those controls into a a catalog and three profiles.

                                    "},{"location":"demonstrations-content/#creating-an-ssp-using-trestle-author","title":"Creating an SSP using trestle author.","text":"

                                    trestle author ssp-generate and trestle author ssp-assemble allow users to generate first a set of markdown documents to allow easy editing of control responses and second to reassemble that information up into an OSCAL ssp document. This is a 'baseline' demonstration with more sophisticated updates expected in the near term.

                                    "},{"location":"demonstrations-content/#trestle-repository-api-trestlecorerepository","title":"Trestle Repository API (trestle.core.repository)","text":"

                                    trestle.core.repository is an API which abstracts users from the file system of a trestle repository. It provides a way for external developers to access a trestle repository without relying on presumptions (such as cwd being within the repository). Find the demo here.

                                    "},{"location":"demonstrations-content/#task-examples","title":"Task examples","text":""},{"location":"demonstrations-content/#convert-a-spreadsheet-into-a-component-definition","title":"Convert a spreadsheet into a component-definition","text":"

                                    This demonstration shows how to use the trestle task xlsx-to-oscal-cd functionality.

                                    "},{"location":"demonstrations-content/#convert-a-xccdf-result-into-a-partial-assessment-results","title":"Convert a xccdf result into a partial assessment-results","text":"

                                    This demonstration shows how to use the trestle task xccdf_result_to_oscal_ar functionality.

                                    "},{"location":"errors/","title":"Known errors and limitations","text":""},{"location":"errors/#utf-8-encoding-only","title":"utf-8 encoding only","text":"

                                    Trestle supports only utf8 as a file text-encoding. If non-utf8 files are encountered, errors will be reported / thrown. Trestle provides a script that may be used to convert files to utf8 in a destructive manner that may change the file contents.

                                    WARNING: This script is potentially destructive and may remove / damage content. Ensure you have a backup before use.

                                    "},{"location":"license/","title":"License","text":"
                                                                     Apache License\n                           Version 2.0, January 2004\n                        https://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n
                                    "},{"location":"maintainers/","title":"Maintainers","text":"

                                    Trestle was designed and open sourced by a team based at IBM Research and others around the world. The list includes:

                                    Alejandro Jose Leiva Palomo AleJo2995

                                    Christopher Butler butler54

                                    Lou Degenaro degenaro

                                    Frank Suits fsuits

                                    Jennifer Power jpower432

                                    Manjiree Gadgil mrgadgil

                                    Vikas Agarwal vikas-agarwal76

                                    "},{"location":"mkdocs_code_of_conduct/","title":"Code of Conduct","text":"

                                    The code of conduct now resides at the organization level in the community repository. Please visit https://github.com/oscal-compass/community/blob/main/CODE_OF_CONDUCT.md to review the common code of conduct.

                                    Note: The code of conduct is subject to change as compliance-trestle is on-boarded as a CNFC sandbox project.

                                    "},{"location":"python_trestle_setup/","title":"Install trestle in a python virtual environment","text":"

                                    There are a few things you need to to start using trestle:

                                    • Make sure you have a working and recent Python environment
                                    • Set up a Python virtual environment
                                    • Download and install trestle
                                    • Confirm it is working properly
                                    • Create a trestle workspace
                                    "},{"location":"python_trestle_setup/#confirm-you-have-python-installed","title":"Confirm you have python installed","text":"
                                    • Ensure you have a modern Python (3.9, 3.10, 3.11).
                                    $ python -V\nPython 3.9.2\n
                                    "},{"location":"python_trestle_setup/#setup-a-virtual-environment","title":"Setup a virtual environment","text":"

                                    There are many ways to do this on Windows, Mac and Linux and with different Python installations, so please consult the documentation associated with your platform. Below is how it works on a typical Linux platform.

                                    $ cd\n$ python -m venv venv.trestle\n$ source venv.trestle/bin/activate\n(venv.trestle)$\n
                                    • Ensure you have a modern pip (19.x or greater).
                                    (venv.trestle)$ python -m pip --version\npip 19.2.3 from /home...\n

                                    You should probably upgrade your pip to the latest version with:

                                    (venv.trestle)$ python -m pip install --upgrade pip\n

                                    Details can be found at Installation - pip documentation

                                    "},{"location":"python_trestle_setup/#install-trestle","title":"Install trestle","text":"
                                    • Install compliance-trestle.
                                    (venv.trestle)$ python -m pip install compliance-trestle\nLooking in indexes: https://pypi.org/simple,...\n
                                    "},{"location":"python_trestle_setup/#confirm-trestle-is-installed-properly","title":"Confirm trestle is installed properly","text":"
                                    • Check trestle viability (and view help).
                                    (venv.trestle)$ trestle -h\nusage: trestle [-h]\n{assemble,author,create,describe,href,import,init,merge,partial-object-validate,remove,replicate,split,task,validate,version}\n...\n
                                    Full help text
                                    Manage OSCAL files in a human friendly manner.\n\npositional arguments:\n  {assemble,author,create,describe,href,import,init,merge,partial-object-validate,remove,replicate,split,task,validate,version}\nassemble            Assemble all subcomponents from a specified trestle model into a single JSON/YAML file under\n                        dist.\n    author              trestle author, a collection of commands for authoring compliance content outside of OSCAL.\n    create              Create a sample OSCAL model in trestle project or create new elements within a given model.\n    describe            Describe contents of a model file including optional element path.\n    href                Change href of import in profile to point to catalog in trestle project. This command is\n                        needed when generating an SSP with a profile that imports a catalog from a temporary location\n                        different from the final intended location of the catalog. Omit the href argument to see the\n                        list of current imports in the profile.\n    import              Import an existing full OSCAL model into the trestle project.\n    init                Initialize a trestle working directory.\n    merge               Merge subcomponents on a trestle model.\n    partial-object-validate\n                        Direct validation any oscal object in a file, including list objects.\n    remove              Remove a subcomponent to an existing model.\n    replicate           Replicate a top level model within the trestle directory structure.\n    split               Split subcomponents on a trestle model.\n    task                Run arbitrary trestle tasks in a simple and extensible methodology.\n    validate            Validate contents of a trestle model in different modes.\n    version             Output version info for trestle and OSCAL.\n\noptional arguments:\n  -h, --help            show this help message and exit\n
                                    "},{"location":"python_trestle_setup/#create-a-trestle-workspace","title":"Create a trestle workspace","text":"
                                    • Create trestle workspace.
                                    (venv.trestle)$ mkdir trestle.workspace\n(venv.trestle)$ cd trestle.workspace\n(venv.trestle)$ trestle init\nInitialized trestle project successfully in /home/<user>/trestle.workspace\n

                                    Congratulations! You now have a working trestle workspace for safe manipulation of OSCAL documents!

                                    "},{"location":"trestle_author/","title":"Trestle CLI for Governance of Authored Documents","text":"

                                    This document is organized in a multiple collapsable sections for ease of use. Start by reading the overview and setting up the Trestle workspace and then proceed to other sections, to learn more about Trestle authoring capabilities.

                                    "},{"location":"trestle_author/#contents","title":"Contents","text":"1. Overview 2. Setting up the Trestle workspace 3. Authoring of Documents Documents Structural Enforcement 4. Authoring of OSCAL Models"},{"location":"trestle_author/#overview","title":"Overview","text":"

                                    The premise of trestle is to support managing compliance artifacts as code. When this is considered, many organisations using {github|gitlab|bitbucket} rely on markdown documents for documentary artifacts that may either directly or indirectly support compliance efforts.

                                    To support this, trestle has the concept of 'governing' documents that are authored documents: Where structural conditions are enforced on the markdown documents to allow automation and to ensure business processes are met.

                                    Living in the GitOps world this capability is anchored with markdown files as the core of the workflows. Currently drawio files are also supported for a subset of enforcement mechanisms.

                                    Setting Up Templates and Documents Via CLI

                                    Trestle allows the setup of templates and governed documents in a several different ways based on the nature of the needed governance.

                                    Definitions used in this section:

                                    • document - a markdown or drawio file that needs to be validated against some template.
                                    • template - an individual markdown or drawio file containing metadata and/or headings against which the documents will be validated.
                                    • task - a name of the folders containing documents and their respective templates.
                                    • template folder - an individual folder containing the templates that documents needs to be validated against.

                                    You can set up multiple different tasks and types of validations in the same workspace.

                                    Setup Trestle for:

                                    docs - Validating documents against one specific template (one template per task) Template Versioning"},{"location":"trestle_author/#why-is-this-capability-in-trestle","title":"Why is this capability in trestle?","text":"

                                    While trestle provides editing support for OSCAL there is an unfortunate truth that for some compliance workflows:

                                    1. OSCAL does not cover the lower level operational workflows.
                                    2. Some users will not be comfortable editing in json/yaml/xml formats

                                    The markdown centric workflows allow transition path where capability is being developed

                                    "},{"location":"trestle_author/#setting-up-the-trestle-workspace","title":"Setting up the Trestle workspace","text":"

                                    To work with governed documents, you would need to initialize the Trestle workspace and create your first governed document and template.

                                    To create a trestle workspace that will contain all your templates and governed documents:

                                    mkdir my_workspace\ncd my_workspace\ntrestle init --govdocs\n>>> Initialized trestle project successfully in [user_path]/my_workspace\n

                                    The templates will be located in the /my_workspace/.trestle/author/. Please note that if you use MacOS or Linux distribution, by default .trestle will be hidden. You will need to reconfigure your system to show hidden folders if you want to see them listed.

                                    "},{"location":"trestle_author/#markdown-structural-enforcement","title":"Markdown structural enforcement","text":"

                                    Trestle templating enforces the documents to follow a specific structure. There are two ways in which structure is enforced in a document against template:

                                    1. Enforcing a YAML header (metadata) structure at the top of the markdown document.
                                    2. Enforcing a heading structure within the markdown document.

                                    Each document is validated against a specific template, see CLI section below on information on how to specify which template the document should be validated against.

                                    "},{"location":"trestle_author/#enforcing-yaml-header-metadata-structure","title":"Enforcing YAML header (metadata) structure","text":"

                                    Each template and document contains metadata in form of a YAML header that is placed on top. When the document is created (i.e. trestle docs setup) the metadata is copied from the template to the newly created document.

                                    Below is an example of a markdown file that contains YAML header:

                                    ---\ngroceries:\ngrocery1:\n  name: apple\n  type: fruit\n  bought-in: Local market\ngrocery2:\n  name: potato\n  type: vegetable\n  bought-in: Local market\ndate: 01-01-2022\nnot-important-field: not important\nx-trestle-version: 1.0.0\nx-trestle-ignore: not-important-field, bought-in\n---\n# The rest of my document\n

                                    Each field in the YAML header follows the key: value format. For YAML header we validate the structure and the presence of the \"keys\" and not the \"values\".

                                    The document YAML header(metadata) is said to be valid against the template, if and only if:

                                    1. It contains all keys from the template EXCEPT the keys that either:
                                    2. Start with x-trestle
                                    3. Are listed under the x-trestle-ignore key (i.e. x-trestle-ignore: not-important-field, bought-in)
                                    4. The version under x-trestle-template-version: key is matching the template.
                                    5. No new keys were added to the document.

                                    For example, this change to the YAML header above is acceptable:

                                    ---\ngroceries:\n  grocery1:\n      name: pear\n      type: fruit\n      bought-in: Superstore\n  grocery2:\n      name: potato\n      type: vegetable\n      bought-in: Local market\ndate: 10-10-2023\nnot-important-field: not important\nx-trestle-version: 1.0.0\nx-trestle-ignore: not-important-field, bought-in\n---\n# The rest of my document\n
                                    "},{"location":"trestle_author/#enforcing-heading-structure","title":"Enforcing heading structure","text":"

                                    Markdown headings are considered to be nested based on the heading level (i.e. number of #). For example, ## 1.1 Lower level heading is below # 1. top level heading.

                                    The document body is said to be valid against the template, if and only if,

                                    1. It contains all the headings provided in the template.
                                    2. No new headings were added at the top level (i.e. # New heading is not allowed).
                                    3. All original headings are in the same order as in the template.
                                    4. All headings must be in the hierarchical order (i.e. # Heading then ### Heading then ## Heading is invalid).
                                    5. If the --governed-heading option is provided, then document is valid if no keys has changed in the specified governed section.

                                    For example, consider this template as our starting point:

                                    # Template heading 1\nSome text\n# Template heading 2\n## Template sub heading\n

                                    Now we added new sections and ended up with the following document: (note: this document will be valid against the template above)

                                    # Template heading 1\nContent for heading one\n## Non-required sub header\nContent for non-required sub header\n# Template heading 2\nContent for heading two\n## Template sub heading\nContent for template sub heading\n### non required sub-sub heading\nThis sub-sub heading is okay\n

                                    However, violations such as adding or removing a heading at the top level are not acceptable:

                                    # Template heading 1\nContent for heading one\n## Non-required sub header\nContent for non-required sub header\n# Template heading 2\nContent for heading two\n## Template sub heading\nContent for template sub heading\n# Top level heading that is not okay <<< NOT OKAY\n

                                    For each of the headings - the text of the heading is enforced with one caveat:

                                    • If the template heading text is wrapped in curly brackets {} then the name is not measured e.g. # {Insert title here}.
                                    folders - Validating documents against multiple templates and ensuring folder structure (multiple individual templates per task) headers - Validate only the headers against a global or a specific template"},{"location":"trestle_author/#drawio-enforcement-mechanisms","title":"Drawio enforcement mechanisms","text":"

                                    Drawio or diagrams.net is a diagramming platform which has significant use for architecture diagrams. In the context of governance of content, trestle is supporting enforcement of metadata.

                                    Drawio (or mxgraph) files have a set of data fields. In a drawio file this is available in the edit menu as edit data. The diagram below shows how to access the (meta)data.

                                    The data presents as a set of key-value pairs which can be edited (see below). The data is bound to each tab in a drawio file. The trestle CLI currently expects that metadata (whether from the template or file to be measured) is in the first tab when editing the draw io file.

                                    "},{"location":"trestle_author/#validating-documents-against-one-specific-template","title":"Validating documents against one specific template","text":"

                                    In this section we describe the functionality of trestle author docs command.

                                    author docs is designed to support enforcing and generating templating markdown files within a single folder based on a task name. Currently author docs supports markdown files only.

                                    "},{"location":"trestle_author/#creating-new-tasktemplate","title":"Creating new task/template","text":"

                                    To create a new task with the necessary directory structures for running governed docs validation, run:

                                    trestle author docs setup -tn my_task_name

                                    This will create a template folder and a single template: TRESTLE_ROOT/.trestle/author/my_task_name/0.0.1/template.md. As well as an empty document folder: TRESTLE_ROOT/my_task_name/ The template will be applied to all markdown files in the task i.e.: TRESTLE_ROOT/my_task_name/*.md.

                                    "},{"location":"trestle_author/#extra-options","title":"Extra options","text":"
                                    • You can create different versions of the template by specifying the version via --template-version flag. See Template Versioning section for more information. By default if no version is provided 0.0.1 will be used.
                                    "},{"location":"trestle_author/#creating-new-document-for-the-task","title":"Creating new document for the task","text":"

                                    To create a new document that confirms to a template run:

                                    trestle author docs create-sample -tn my_task_name

                                    This will create a sample document in: TRESTLE_ROOT/my_task_name/my_task_name_000.md. Once created this document will be a complete copy of the template, however you can modify this file with your own content.

                                    "},{"location":"trestle_author/#extra-options_1","title":"Extra options","text":"
                                    • This command has no extra options
                                    "},{"location":"trestle_author/#validating-the-template","title":"Validating the template","text":"

                                    To ensure that the markdown in the template is parseable run:

                                    trestle author docs template-validate -tn my_task_name

                                    "},{"location":"trestle_author/#extra-options_2","title":"Extra options","text":"
                                    • If --governed-heading 'heading name' (-gh) is passed it ensures that the required heading exists.
                                    • If --header-validate (-hv) is passed the header will be validated as well.
                                    • If --header-only-validate (-hov) only the header and NOT the body will be validated
                                    "},{"location":"trestle_author/#validating-the-documents-against-the-template","title":"Validating the documents against the template","text":"

                                    To validate the documents against a template run:

                                    trestle author docs validate -tn my_task_name

                                    This will take the TRESTLE_ROOT/.trestle/author/my_task_name/template.md template and validate all markdown files here: TRESTLE_ROOT/my_task_name/*.md.

                                    Running the command will validate that markdown body in the document is valid against the template. Please note that by default the header will not be validated. See extra options for more validation options. To learn more on what exactly is validated please refer to Documents Structural Enforcement section in this document.

                                    "},{"location":"trestle_author/#extra-options_3","title":"Extra options","text":"
                                    • If --governed-heading (-gh) is passed it will ensure that the governed content was not modified. Governed content comes in the key: value format:
                                         # Governed section\n     **Content Type:**  Foo\n     **Author(s):**  Bah\n     **Executive Owner:**  Stuff\n     **Technical Approver:**   John Doe (approved)\n     **Version:** 1.0.1\n

                                    Running trestle author docs validate -tn docs_task -gh=\"Governed section\" will ensure this content is present in the document.

                                    • If --ignore ^_.* (-ig) is passed it will validate all files except folders and files that start with underscore _. Use this option when you would like to ignore any folders or files that match given regular expression.
                                    • If --header-validate (-hv) is passed the header will be validated as well.
                                    • If --header-only-validate (-hov) is passed only the header and NOT the body will be validated.
                                    • If --readme-validate (-rv) is passed README.md will be validated as well, otherwise it is ignored.
                                    • If --recurse (-r) is passed the documents in the subfolders will also be validated. By default author docs only indexes a flat directory.
                                    • If --template-version 1.0.0 (-tv) is passed the header field x-trestle-template-version will be ignored and document will be forcefully validated against template of version 1.0.0. Use this for testing purposes only when you need to validate the document against a specific template. By default the template version will be determined based on x-trestle-template-version in the document.
                                    "},{"location":"trestle_author/#validating-the-documents-against-different-templates","title":"Validating the documents against different templates","text":"

                                    Validation against multiple templates can be done when there is a scenario where you have multiple templates that will have multiple instances. In this particular case you can have a 1:1 relationship between the template and the instance document you are creating out of it, so validation can be performed based on template type and version of that particular template defined in headers.

                                    For that to happen you will need to provide your template with the following parameter at the yaml header level, matching the type of template to be implemented so that the validation can occur:

                                    x-trestle-template-type: insert_template_type_here

                                    Please, take into consideration that for the validation to happen you will also need to provide each instance document in the task folder a field called x-trestle-template-type: insert_template_type_here in the yaml header matching with the template name.

                                    ---\nauthors: tmp\nowner: tmp\nvalid:\nfrom: null\nto: null\nx-trestle-template-type: insert_template_type_here\n---\n

                                    With that, you will be able to create more than 1 instance document per template and give the instance the desired name.

                                    For instance, let\u00b4s consider the next folder structure:

                                    trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_2\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 a_template.md\n\u2503 \u2503 \u2503 \u2503 \u2523 another_template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 arhitecture.drawio\n\u2503 \u2517 config.ini\n\ntrestle_root\n \u2523 .trestle\n \u2523 my_task_2\n \u2503 \u2523 sample_folder_0\n \u2503 \u2503 \u2523 a_template_1.md\n \u2503 \u2503 \u2523 a_template_2.md\n \u2503 \u2503 \u2523 arhitecture_1.drawio\n \u2503 \u2503 \u2517 another_template_123.md\n

                                    If you noticed, names are no longer needed to match with exact template names, and that\u00b4s because validation will run through x-trestle-template-type field defined at the instance header, not through the name.

                                    To validate the documents against their respective templates using x-trestle-template-type, run:

                                    trestle author docs validate -tn my_task_name -vtt

                                    Now, -vtt stands for validate template type. Validate template type option will provide you the ability to have more than 1 instance per template validated.

                                    "},{"location":"trestle_author/#validating-against-multiple-templates","title":"Validating against multiple templates","text":"

                                    In this section we describe the functionality of trestle author folders command.

                                    author folders is designed to allow the assembly of groups of templates where each folder contains unique content. This command will validate that both: structure (i.e. all template documents are present) and content is preserved in the folder. Trestle author folders supports validation of both markdown and drawio files. Note that headers / metadata must be specified in each applicable template.

                                    "},{"location":"trestle_author/#creating-new-task-folder","title":"Creating new task folder","text":"

                                    To create a new task folder run:

                                    trestle author folders setup -tn my_task_2

                                    This will create a template folder with the following structure:

                                    trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_2\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 a_template.md\n\u2503 \u2503 \u2503 \u2503 \u2523 another_template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 arhitecture.drawio\n\u2503 \u2517 config.ini\n

                                    Each task folder is required to meet template requirements for all: a_template.md, another_template.md, and template.drawio. The names, numbers, and nesting of folders is user specifiable, however, unlike docs the names must be carried over to each instances.

                                    "},{"location":"trestle_author/#extra-options_4","title":"Extra options","text":"
                                    • You can create different versions of the template by specifying the version via --template-version flag. See Template Versioning section for more information. By default if no version is provided 0.0.1 will be used.
                                    "},{"location":"trestle_author/#creating-new-documents-for-the-task","title":"Creating new documents for the task","text":"

                                    Following the similar structure of docs, measurement occurs in the my_task_2 where this structure is enforced for every directory.

                                    To create a new folder with documents for the task run:

                                    trestle author folders create-sample -tn my_task_2

                                    This will create a subfolder in the my_task_2 with the same content as in template folder. Running it twice will result in:

                                    trestle_root\n \u2523 .trestle\n \u2523 my_task_2\n \u2503 \u2523 sample_folder_0\n \u2503 \u2503 \u2523 a_template.md\n \u2503 \u2503 \u2523 arhitecture.drawio\n \u2503 \u2503 \u2517 another_template.md\n\n \u2503 \u2517 sample_folder_1\n \u2503 \u2503 \u2523 a_template.md\n \u2503 \u2503 \u2523 arhitecture.drawio\n \u2503 \u2503 \u2517 another_template.md\n
                                    "},{"location":"trestle_author/#extra-options_5","title":"Extra options","text":"
                                    • This command has no extra options
                                    "},{"location":"trestle_author/#validating-the-templates","title":"Validating the templates","text":"

                                    To validate the documents against the template run:

                                    trestle author folders template-validate -tn my_task_2

                                    This will ensure that the respective template files are parseable.

                                    "},{"location":"trestle_author/#extra-options_6","title":"Extra options","text":"
                                    • This command has no extra options
                                    "},{"location":"trestle_author/#validating-the-documents-against-templates","title":"Validating the documents against templates","text":"

                                    The validation in trestle author folder runs similarly as in docs but now each document will be validated against the template with the same name as in the template folder.

                                    To validate the documents against their respective templates, run:

                                    trestle author folders validate -tn my_task_name

                                    This will validate all files. Please note that all files from the template folder must be present in the individual document folders.

                                    "},{"location":"trestle_author/#extra-options_7","title":"Extra options","text":"
                                    • If --governed-heading (-gh) is passed it will ensure that the governed content was not modified. Governed content comes in the key: value format:
                                         # Governed section\n   **Content Type:**  Foo\n   **Author(s):**  Bah\n   **Executive Owner:**  Stuff\n   **Technical Approver:**   John Doe (approved)\n   **Version:** 1.0.1\n

                                    Running trestle author docs validate -tn docs_task -gh=\"Governed section\" will ensure this content is present in the document.

                                    • If --ignore ^_.* (-ig) is passed it will validate all files except folders and files that start with underscore _. Use this option when you would like to ignore any folders or files that match given regular expression.
                                    • If --header-validate (-hv) is passed the header will be validated as well.
                                    • If --header-only-validate (-hov) is passed only the header and NOT the body will be validated.
                                    • If --readme-validate (-rv) is passed README.md will be validated as well, otherwise it is ignored.
                                    • If --recurse (-r) is passed the documents in the subfolders will also be validated. By default author docs only indexes a flat directory.
                                    • If --template-version 1.0.0 (-tv) is passed the header field x-trestle-template-version will be ignored and document will be forcefully validated against template of version 1.0.0. Use this for testing purposes only when you need to validate the document against a specific template. By default the template version will be determined based on x-trestle-template-version in the document.
                                    "},{"location":"trestle_author/#validating-the-documents-against-different-templates_1","title":"Validating the documents against different templates","text":"

                                    Validation against multiple templates as stated before can be done, but there is another scenario that you can leverage on trestle to have multiple documents in the task folder corresponding to a single template.

                                    For that to happen you will need to provide your template with the following parameter at the yaml header level, matching the type of template to be implemented so the validation can occur:

                                    x-trestle-template-type: insert_template_type_here

                                    Please, take into consideration that for the validation to happen you will also need to provide each instance document in the task folder a field called x-trestle-template-type: insert_template_type_here in the yaml header matching with the template name.

                                    ---\nauthors: tmp\nowner: tmp\nvalid:\nfrom: null\nto: null\nx-trestle-template-type: insert_template_type_here\n---\n

                                    With that, you will be able to create more than 1 instance document per template and give the instance the desired name.

                                    For instance, let\u00b4s consider the next folder structure:

                                    trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_2\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 a_template.md\n\u2503 \u2503 \u2503 \u2503 \u2523 another_template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 arhitecture.drawio\n\u2503 \u2517 config.ini\n\ntrestle_root\n \u2523 .trestle\n \u2523 my_task_2\n \u2503 \u2523 sample_folder_0\n \u2503 \u2503 \u2523 a_template_1.md\n \u2503 \u2503 \u2523 a_template_2.md\n \u2503 \u2503 \u2523 arhitecture_1.drawio\n \u2503 \u2503 \u2517 another_template_123.md\n

                                    If you noticed, names are no longer needed to match with exact template names, and that\u00b4s because validation will run through x-trestle-template-type field defined at the instance header, not through the name.

                                    To validate the documents against their respective templates using x-trestle-template-type, run:

                                    trestle author folders validate -tn my_task_name -vtt

                                    Now, -vtt stands for validate template type. Validate template type option will provide you the ability to have more than 1 instance per template validated.

                                    "},{"location":"trestle_author/#validate-only-the-headers-against-a-global-or-a-specific-template","title":"Validate only the headers against a global or a specific template.","text":"

                                    In this section we describe the functionality of trestle author headers command.

                                    Trestle author headers supports a slightly different usecase than that of docs and folders above as only the YAML headers will be validated. This command can be useful when one does not care about the markdown structure and might want to use global templates (templates that are shared across multiple tasks).

                                    With headers template folder can contain both .md and .drawio files and each file will be validated against the template that matches the extension. Also headers allow user to have global templates that can be shared across multiple tasks.

                                    "},{"location":"trestle_author/#creating-new-tasktemplate_1","title":"Creating new task/template","text":"

                                    To create a new task run:

                                    trestle author headers setup -tn my_task_3

                                    This will create a template folder with the following format:

                                    trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_3\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 template.drawio\n\u2503 \u2517 config.ini\n
                                    "},{"location":"trestle_author/#extra-options_8","title":"Extra options","text":"
                                    • If --global (-g) is passed then __global__ then it will create trestle_root/.trestle/author/__global__ folder. Use this when you would like to use same template for multiple tasks.
                                      trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 __global__\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 template.drawio\n\u2503 \u2517 config.ini\n
                                    • You can create different versions of the template by specifying the version via --template-version flag. See Template Versioning section for more information. By default if no version is provided 0.0.1 will be used.
                                    "},{"location":"trestle_author/#creating-new-documents","title":"Creating new documents","text":"

                                    As of now this command does not support the automatic creation of the sample documents.

                                    "},{"location":"trestle_author/#validating-the-templates_1","title":"Validating the templates","text":"

                                    To validate the documents against the template run:

                                    trestle author headers template-validate -tn my_task_3

                                    This will ensure that the respective template files are parseable.

                                    "},{"location":"trestle_author/#extra-options_9","title":"Extra options","text":"
                                    • This command has no extra options
                                    "},{"location":"trestle_author/#validating-the-documents","title":"Validating the documents","text":"

                                    To validate the documents against the template run:

                                    trestle author headers validate -tn my_task_3

                                    This will validate all files within the directory against the templates (of the matching task name) by matching the extensions. Please note that only headers will be validated. There is no option to validate the body.

                                    "},{"location":"trestle_author/#extra-options_10","title":"Extra options","text":"
                                    • If --global (-g) is passed it will create trestle_root/.trestle/author/__global__ folder. Use this when you would like to use same template for multiple tasks.
                                    • If --ignore ^_.* (-ig) is passed it will validate all files except folders and files that start with underscore _. Use this option when you would like to ignore any folders or files that match given regular expression.
                                    • If --readme-validate (-rv) is passed README.md will be validated as well, otherwise it is ignored.
                                    • If --recurse (-r) is passed the documents in the subfolders will also be validated. By default author docs only indexes a flat directory.
                                    • If --template-version 1.0.0 (-tv) is passed the header field x-trestle-template-version will be ignored and document will be forcefully validated against template of version 1.0.0. Use this for testing purposes only when you need to validate the document against a specific template. By default the template version will be determined based on x-trestle-template-version in the document.
                                    "},{"location":"trestle_author/#template-versioning","title":"Template versioning","text":""},{"location":"trestle_author/#prerequisite","title":"Prerequisite:","text":"

                                    This section assumes that you have an existing Trestle workspace initialized, with existing template and governed documents. Please follow steps in the section Setting up the Trestle Workspace if you don't have one.

                                    Trestle provides the capability to version the templates and the documents via x-trestle-template-version field in the header.

                                    Consider an example where we have a governed document called Decision 1 that we now need to update to contain a new header field approved-status and a new required heading Heading n at the end, as demonstrated in the Figure below:

                                    The intended workflow in this scenario is to:

                                    1.Create a new version of the decisions template:

                                    cd my_workspace \ntrestle author docs setup -tn decisions -tv 0.1.1\n>>> Set template version to 0.1.1.\n>>> Template file setup for task decisions at .trestle/author/decisions/0.1.1/template.md\n>>> Task directory is decisions\n

                                    Add the new required content to the newly created template. In our example simply copy-paste all content from the .trestle/author/decisions/0.1.0/template.md and add the newly required fields.

                                    2.Create a new instance of that template.

                                    trestle author docs create-sample -tn decisions -tv 0.1.1\n>>> Set template version to 0.1.1.\n

                                    This step will create a copy of the template of version 0.1.1.

                                    Now you will need to fill the documents with the updated information and new fields.

                                    3.(Optional) Delete the old document.

                                    Now that you have a new version of the document, you can delete the old one if you no longer need it. You can also keep it if you would like to maintain a history of updates.

                                    4.Run validation.

                                    After filling the contents to the new version of the template, you can run the validation to ensure that everything works as expected.

                                    trestle author docs validate -tn decisions\n>>> Instances will be validated against template version specified in their headers.\n>>> VALID: decisions/decision_000.md\n
                                    "},{"location":"trestle_author/#oscal-authoring","title":"OSCAL Authoring","text":""},{"location":"trestle_author/#catalog-authoring","title":"Catalog authoring","text":"

                                    CLI evocation:

                                    1. To generate markdowns for editing a catalog

                                    trestle author catalog-generate

                                    1. To assemble markdowns to a JSON catalog

                                    trestle author catalog-assemble

                                    The catalog author commands allow you to convert a control catalog to markdown and edit its control statement, then assemble markdown back into an OSCAL catalog with the modifications to the statement. Items in the statement may be edited or added. For more details on its usage please see the catalog authoring tutorial.

                                    "},{"location":"trestle_author/#profile-authoring","title":"Profile authoring","text":"

                                    CLI evocation:

                                    1. To generate markdowns for editing a profile

                                    trestle author profile-generate

                                    1. To assemble markdowns to a JSON profile

                                    trestle author profile-assemble

                                    The profile author commands allow you to edit additions made by a profile to its imported controls that end up in the final resolved profile catalog. Only the additions may be edited or added to the generated markdown control files - and those additions can then be assembled into a new version of the original profile, with those additions. For more details on its usage please see the profile authoring tutorial.

                                    "},{"location":"trestle_author/#profile-generation-with-inheritance","title":"Profile generation with inheritance","text":"

                                    CLI evocation:

                                    trestle author profile-inherit

                                    The profile-inherit sub-command takes a given parent profile and filters its imported controls based inherited controls from a given SSP.

                                    The leveraged SSP is evaluated based on whether provided and responsibility statements for all by-component fields are set for each applicable control, as well as the implementation status. All components must have exported provided statements, no exported responsibility statements, and an implementation status of implemented in order for a control to be filtered from the output profile (i.e. controls delta profile).

                                    As with the other related author commands, if an existing destination file already exists, it is not updated if no changes would be made.

                                    For more details on its usage please see the ssp-filter tutorial.

                                    "},{"location":"trestle_author/#ssp-authoring","title":"SSP authoring","text":"

                                    CLI evocation:

                                    1. To generate markdowns for editing SSP

                                    trestle author ssp-generate

                                    1. To assemble markdowns to a JSON SSP

                                    trestle author ssp-assemble

                                    The ssp-generate sub-command creates a partial SSP (System Security Plan) from a profile and optional yaml header file. ssp-assemble can then assemble the markdown files into a single json SSP file.

                                    For more details on its usage please see the ssp authoring tutorial.

                                    "},{"location":"trestle_author/#ssp-content-filtering","title":"SSP Content Filtering","text":"

                                    CLI evocation:

                                    trestle author ssp-filter

                                    The ssp-filter sub-command takes a given SSP and filters its contents based on a given profile, list of components, control implementation status and/or control origination.

                                    If filtering by profile, the SSP is assumed to contain a superset of controls needed by the profile, and the filter operation generates a new SSP with just the controls needed by that profile. If the profile references a control not in the SSP, the routine fails with an error.

                                    If filtering by components, a colon-delimited list of components should be provided, with This system as the default name for the overall required component for the entire system. Case and spaces are ignored in the component names, so the names could be specified as --components \"this system: my component\". The resulting, filtered ssp will have updated implemented requirements with filtered by_components on each requirement, and filtered by_components on each statement.

                                    If filtering by control implementation status, a comma-delimited list of implementation status values should be provided. These values must comply with the OSCAL SSP format references's allowed values, which are as follows: implemented, partial, planned, alternative, and not-applicable.

                                    If filtering by control origination, a comma-delimited list of control origination values should be provided. These values must comply with the OSCAL SSP format references's allowed values for the control origination property, which are as follows: system-specific, inherited, organization, customer-configured, and customer-provided.

                                    You may filter by a combination of a profile, list of component names, implementation statuses, and control origination values.

                                    As with the other related author commands, if an existing destination file already exists, it is not updated if no changes would be made.

                                    For more details on its usage please see the ssp-filter tutorial.

                                    "},{"location":"trestle_author_jinja/","title":"Trestle author jinja - output templating support for oscal documents.","text":"

                                    Unfortunately OSCAL documents are not yet universally accepted. Therefore to support various OSCAL and non-OSCAL compliance workflows trestle author jinja is designed to provide end users with the ability to use jinja to produce customized output. This complements the more structured commands trestle author catalog-{assemble|generate}, trestle author profile-{assemble|generate} and trestle author ssp-{assemble|generate} and allows arbitrary use of jinja.

                                    "},{"location":"trestle_author_jinja/#jinja-and-jinja-extensions-provided-by-trestle","title":"Jinja and jinja extensions provided by trestle.","text":"

                                    Jinja is a powerful templating engine that is both more flexible that pure 'Moustache' approaches, and not coupled to a particular web application server (as an example Django templates). Users are encouraged to review the template designer documentation for jinja as all core functionality is exposed.

                                    Trestle's implementation of the Jinja command works in the following way:

                                    1. The template search space, by default, is relative to the current working directory.
                                    2. Trestle can inject a lookup table, into the jinja variables to contain booleans / substitutions required by end users using Moustache style variable substitutions.
                                    3. Trestle can provide a number of interfaces to OSCAL objects, currently a resolved catalog and a SSP, into jinja.
                                    4. Trestle supports custom jinja tags for importing.
                                    5. The jinja templating is recursive, to ensure all jinja tags are resolved as appropriate.

                                    More details will be on each of these points below.

                                    "},{"location":"trestle_author_jinja/#cli-invocation","title":"CLI invocation","text":"

                                    Note the examples here use markdown, however, jinja can quite easily target xml or html if used w/o specific markdown content. trestle author jinja -i input_template.md.jinja -o output_file.md -ssp SSP_NAME -p PROFILE_NAME -lut lookup_table.yaml -elp lut.prefix

                                    • -i input file path, relative to cwd. Users are encouraged to use the file_name.target_extension.jinja best practice as it helps mitigate issues, however is not required.
                                    • -o final output path, relative to cwd.
                                    • -ssp (optional) ssp name (in the trestle project). When used the jinja template will have a ssp_md_writer variable exposed to use.
                                    • -p (optional) profile name (in the trestle project). When used the jinja template will have resolved_catalog and catalog_interface variables to use.
                                    • -lut (optional) loads yaml into a dictionary in python for which each (top level) variable is available in jinja.
                                    • -elp (optional) a period separated prefix for the variables in the lookup table. E.g. if the lut contained banana: yellow and the prefix was fruit.tropical using {{ fruit.tropical.banana }} would print out yellow in the jinja template.
                                    • -bf (optional) use to provide a custom formatting of the substituted parameters in the text with brackets or markup formatting. Use dot (.) to indicate where the parameter value will be written. E.g. -bf *.* to italicize all substituted parameters, -bf Prefix:. to add Prefix: to all parameters, and -bf [.] to put square brackets around the parameters.
                                    • -vap (optional) use to specify a --value-assigned-prefix in front of parameters that have values assigned by the profile. An example would include the organization doing the assignment, e.g. -vap \"ACME Assignment:\" This is identical to the behavior of profile-resolve.
                                    • -vnap (optional) use to specify a --value-not-assigned-prefix in front of parameters that do not have values assigned by the profile. An example would be -vap \"Assignment:\" This is identical to the behavior of profile-resolve.
                                    "},{"location":"trestle_author_jinja/#sample-jinja-templates","title":"Sample jinja templates","text":"

                                    Below is a sample jinja template for SSP.

                                    template Description Optional args required Simple SSP template Sample ssp jinja template which prints out all control responses and includes a front-matter section -ssp and -p for the ssp json and corresponding profile, respectively. Also requires a frontmatter.md file"},{"location":"trestle_author_jinja/#variable-availability-in-the-jinja-template","title":"Variable availability in the jinja template.","text":""},{"location":"trestle_author_jinja/#lut","title":"LUT","text":"

                                    The lookup table is primarily used for string substitution and to provide variables for basic logic operations in jinja e.g.

                                    The LUT:

                                    names:\nOSCAL: Open Security Compliance Assessment Language\ntrestle_pip: compliance-trestle\ntrestle_module: trestle\nvariables:\nmac_os: true\n

                                    The Jinja template:

                                    Install via pip install {{ names.trestle_pip }} and invoke at the python REPL by import {{ names.trestle_module }}\n\n{% if variables.mac_os %}\nUsers are recommended to use homebrew to install the latest python 3 and then install python within a venv.\n{% endif %}\n

                                    The output:

                                    Install via pip install compliance-trestle and invoke at the python REPL by import trestle\n\nUsers are recommended to use homebrew to install the latest python 3 and then install python within a venv.\n

                                    Users are free to use the LUT to inject more complex variables (arrays of data etc) to use at their own will using standard jinja templating.

                                    "},{"location":"trestle_author_jinja/#resolved-catalog-interface-profile","title":"Resolved catalog interface (profile)","text":"

                                    Passing -p exposes a catalog, resolved from the profile, at catalog and a trestle.core.catalog_interface.CatalogInterface at catalog_interface.

                                    This allows user to perform various task such as iterating ove reach group and printing the group title.

                                    {% for group in catalog_interface.get_all_groups_from_catalog() +%}\n## {{ group.title }} {{ group.class }} \\({{ group.id|upper }}\\)\n
                                    "},{"location":"trestle_author_jinja/#ssp-interface","title":"SSP interface.","text":"

                                    If -ssp is passed a variable within the jinja template called ssp_md_writer is made available which is an instance of trestle.core.ssp_io.SSPMarkdownWriter. -ssp requires that -p has also been set.

                                    This as allows users, as an example to print out a control response, as markdown

                                    #### What is the solution and how is it implemented?\n{{ ssp_md_writer.get_control_response('my_control_id', 3)}}\n
                                    "},{"location":"trestle_author_jinja/#custom-jinja-tags","title":"Custom Jinja tags.","text":"

                                    Trestle provides custom jinja tags for use specifically with markdown: mdsection_include and md_clean_include.

                                    md_clean_include is similar to the native {% include 'sub_template' %} that jinja provides except for the following:

                                    1. md_clean_include will look for yaml headers in the markdown content and exclude it from the template
                                    2. md_clean_include can be used with an optional keyword argument heading_level argument
                                    3. {% md_clean_include 'path_to_file.md' heading_level=2 %}
                                    4. The heading level argument adjusts to (based on the number of hashes) the most significant heading in the document, if headings exist.

                                    mdsection_include is similar to the native md_clean_include except that.:

                                    1. mdsection_include requires an second positional argument which is the title of a heading, from a markdown file, which you want the content from.

                                    2. E.g: {% mdsection_include 'test_markdown.md' '# Header we want' %}

                                    3. mdsection_include can be used with an optional keyword argument heading_level argument similar to md_clean_include

                                    4. {% mdsection_include 'test_markdown.md' '# Header we want' %}

                                    5. The heading level argument adjusts to (based on the number of hashes) the most significant heading in the chosen section, if headings exist.

                                    md_datestamp inserts a date stamp into the output. By default the date is in the format '%Y-%m-%d', e.g. '2021-12-28' and is followed by a double newline to prevent subsequent headings failing to parse correctly. E.g: {% md_datestamp %} results in a date in the format '2021-12-28' being inserted. md_datestamp can be used with the following optional keyword arguments:

                                    1. format where a python datetime strftime format string is provided to format the output. E.g. {% md_datestamp format='%B %d, %Y' %} results in December 28, 2021 being inserted.
                                    2. newline is a boolean to control the addition of a double newline after the inserted date string. For example {% md_datestamp newline=false %} inserts a date in the default format, without additional newlines.
                                    "},{"location":"trestle_author_jinja/#generate-controls-as-individual-markdown-pages","title":"Generate controls as individual markdown pages.","text":"

                                    Trestle's Jinja functionality allows its users to generate individual markdown pages for each control from a resolved profile catalog. Such functionality can be used later on to pack individual pages into docs of various formats.

                                    When --docs-profile or -dp flag is provided as part of the trestle author jinja command, the provided Jinja template will be used to generate a markdown page for each control in each group.

                                    For example, suppose we would like to generate the markdown page for each control that would contain Control Objective, Control Statement, Expected Evidence, Implementation Guidance and say Table of Parameters used for this control. To achieve that, we can create a simple Jinja template that would be used to generate each page:

                                    # Control Page\n\n{{ control_writer.write_control_with_sections(\n   control,\n   profile,\n   group_title, \n   ['statement', 'objective', 'expected_evidence', 'implementation_guidance', 'table_of_parameters'], \n   {\n      'statement':'Control Statement',\n      'objective':'Control Objective', \n      'expected_evidence':'Expected Evidence', \n      'implementation_guidance':'Implementation Guidance', \n      'table_of_parameters':'Control Parameters'\n   }\n   ) \n\n   | safe\n}}\n

                                    The template above, would call a control writer that would print the required sections (specified in the list) with the provided headers (specified in the dictionary).

                                    We can then generate individual markdown pages by executing: trestle author jinja -i profile_to_docs.md.jinja -o controls -p some_profile -dp

                                    This will create a folder named controls, that would contain a folder per each group and a markdown file per each control in that group. Each markdown file would be formatted using the Jinja template above.

                                    The generated markdown files can then be assembled to the docs of the desired format by adding an indexing page.

                                    "},{"location":"api_reference/trestle.cli/","title":"cli","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.cli/#trestle.cli","title":"trestle.cli","text":"

                                    Starting point for the Trestle CLI.

                                    "},{"location":"api_reference/trestle.cli/#trestle.cli.logger","title":"logger","text":""},{"location":"api_reference/trestle.cli/#trestle.cli-classes","title":"Classes","text":""},{"location":"api_reference/trestle.cli/#trestle.cli.Trestle","title":" Trestle (CommandBase) ","text":"

                                    Manage OSCAL files in a human friendly manner.

                                    Source code in trestle/cli.py
                                    class Trestle(CommandBase):\n\"\"\"Manage OSCAL files in a human friendly manner.\"\"\"\n\n    subcommands = [\n        AssembleCmd,\n        AuthorCmd,\n        CreateCmd,\n        DescribeCmd,\n        HrefCmd,\n        ImportCmd,\n        InitCmd,\n        MergeCmd,\n        PartialObjectValidate,\n        RemoveCmd,\n        ReplicateCmd,\n        SplitCmd,\n        TaskCmd,\n        ValidateCmd,\n        VersionCmd\n    ]\n\n    discovered_plugins = {\n        name: importlib.import_module(name)\n        for finder,\n        name,\n        ispkg in pkgutil.iter_modules()\n        if name.startswith('trestle_')\n    }\n\n    logger.debug(discovered_plugins)\n    # This block is uncovered as trestle cannot find plugins in it's unit tests - it is the base module.\n    for plugin, value in discovered_plugins.items():  # pragma: nocover\n        for _, module, _ in pkgutil.iter_modules([pathlib.Path(value.__path__[0], 'commands')]):\n            logger.debug(module)\n            command_module = importlib.import_module(f'{plugin}.commands.{module}')\n            clsmembers = inspect.getmembers(command_module, inspect.isclass)\n            logger.debug(clsmembers)\n            for _, cmd_cls in clsmembers:\n                # add commands (derived from CommandPlusDocs or CommandBase) to subcommands list\n                if issubclass(cmd_cls, CommandBase):\n                    # don't add CommandPlusDocs or CommandBase\n                    if cmd_cls is not CommandPlusDocs and cmd_cls is not CommandBase:\n                        subcommands.append(cmd_cls)\n                        logger.info(f'{cmd_cls} added to subcommands from plugin {plugin}')\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-v', '--verbose', help=const.DISPLAY_VERBOSE_OUTPUT, action='count', default=0)\n        self.add_argument(\n            '-tr', '--trestle-root', help='Path of trestle root dir', type=pathlib.Path, default=pathlib.Path.cwd()\n        )\n
                                    "},{"location":"api_reference/trestle.cli/#trestle.cli.Trestle.discovered_plugins","title":"discovered_plugins","text":""},{"location":"api_reference/trestle.cli/#trestle.cli.Trestle.subcommands","title":"subcommands","text":""},{"location":"api_reference/trestle.cli/#trestle.cli-functions","title":"Functions","text":""},{"location":"api_reference/trestle.cli/#trestle.cli.run","title":"run()","text":"

                                    Run the trestle cli.

                                    Source code in trestle/cli.py
                                    def run() -> None:\n\"\"\"Run the trestle cli.\"\"\"\n    log.set_global_logging_levels()\n    logger.debug('Main entry point.')\n\n    exit(Trestle().run())\n
                                    "},{"location":"api_reference/trestle.common.common_types/","title":"common_types","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types","title":"trestle.common.common_types","text":"

                                    Special types are defined here.

                                    "},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.FixedUuidModel","title":"FixedUuidModel","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.OBT","title":"OBT","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TG","title":"TG","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TG2","title":"TG2","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TopLevelOscalModel","title":"TopLevelOscalModel","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithByComps","title":"TypeWithByComps","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithParamId","title":"TypeWithParamId","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithParts","title":"TypeWithParts","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithProps","title":"TypeWithProps","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithSetParams","title":"TypeWithSetParams","text":""},{"location":"api_reference/trestle.common.const/","title":"const","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.const/#trestle.common.const","title":"trestle.common.const","text":"

                                    Core constants module containing all constants.

                                    "},{"location":"api_reference/trestle.common.const/#trestle.common.const-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ADDED_BY_CONTROL_OWNER","title":"ADDED_BY_CONTROL_OWNER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.AFTER_HASHES_REGEX","title":"AFTER_HASHES_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.AGGREGATES","title":"AGGREGATES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ALIAS_PATH_SEPARATOR","title":"ALIAS_PATH_SEPARATOR: str","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ALLOWED_EXTENSIONS_IN_DIRS","title":"ALLOWED_EXTENSIONS_IN_DIRS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ALT_IDENTIFIER","title":"ALT_IDENTIFIER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_DESC_ELEMENT","title":"ARG_DESC_ELEMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_DESC_FILE","title":"ARG_DESC_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_DESC_MODE","title":"ARG_DESC_MODE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_ELEMENT","title":"ARG_ELEMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_ELEMENT_SHORT","title":"ARG_ELEMENT_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_FILE","title":"ARG_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_FILE_SHORT","title":"ARG_FILE_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_MODE","title":"ARG_MODE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_MODE_SHORT","title":"ARG_MODE_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_VALIDATE","title":"ARG_VALIDATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_VALIDATE_SHORT","title":"ARG_VALIDATE_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ASSESMENT_OBJECTIVE_PART","title":"ASSESMENT_OBJECTIVE_PART","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.BUG_REPORT","title":"BUG_REPORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CACHE_ABS_DIR","title":"CACHE_ABS_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CLOSE_COMMENT","title":"CLOSE_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.COMPONENT_VALUES","title":"COMPONENT_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.COMP_DEF_RULES_PARAM_VALS_TAG","title":"COMP_DEF_RULES_PARAM_VALS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.COMP_DEF_RULES_TAG","title":"COMP_DEF_RULES_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_HEADER","title":"CONTROL_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_IMPLEMENTATION","title":"CONTROL_IMPLEMENTATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_OBJECTIVE_HEADER","title":"CONTROL_OBJECTIVE_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_ORIGINATION","title":"CONTROL_ORIGINATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_REGEX","title":"CONTROL_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_STATEMENT_HEADER","title":"CONTROL_STATEMENT_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DAY_SECONDS","title":"DAY_SECONDS: int","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DISPLAY_NAME","title":"DISPLAY_NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DISPLAY_VERBOSE_OUTPUT","title":"DISPLAY_VERBOSE_OUTPUT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DRAWIO_FILE_EXT","title":"DRAWIO_FILE_EXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.EDITABLE_CONTENT","title":"EDITABLE_CONTENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ELEMENT_WILDCARD","title":"ELEMENT_WILDCARD","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FIELDS_SET","title":"FIELDS_SET","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILE_DIGIT_PREFIX_LENGTH","title":"FILE_DIGIT_PREFIX_LENGTH","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILE_ENCODING","title":"FILE_ENCODING","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILE_URI","title":"FILE_URI","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILTER_BY_COMPONENTS","title":"FILTER_BY_COMPONENTS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILTER_BY_PROFILE","title":"FILTER_BY_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILTER_EXCLUDE_COMPONENTS","title":"FILTER_EXCLUDE_COMPONENTS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.GENERATE_RESOLVED_CATALOG","title":"GENERATE_RESOLVED_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.GUIDELINES","title":"GUIDELINES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HEADER_RULE_ID","title":"HEADER_RULE_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_ALLOWED_SECTIONS","title":"HELP_ALLOWED_SECTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_COMPDEFS","title":"HELP_COMPDEFS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_FO_OUTPUT","title":"HELP_FO_OUTPUT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_LEVERAGED","title":"HELP_LEVERAGED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_MARKDOWN_NAME","title":"HELP_MARKDOWN_NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_OVERWRITE_HEADER_VALUES","title":"HELP_OVERWRITE_HEADER_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_REGENERATE","title":"HELP_REGENERATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_REQUIRED_SECTIONS","title":"HELP_REQUIRED_SECTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_SECTIONS","title":"HELP_SECTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_SET_PARAMS","title":"HELP_SET_PARAMS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_VERSION","title":"HELP_VERSION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_YAML_PATH","title":"HELP_YAML_PATH","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HOUR_SECONDS","title":"HOUR_SECONDS: int","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HREF","title":"HREF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HTTPS_URI","title":"HTTPS_URI","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IDX_SEP","title":"IDX_SEP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_POINT","title":"IMPLEMENTATION_POINT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_POINT_EXTERNAL","title":"IMPLEMENTATION_POINT_EXTERNAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_STATUS","title":"IMPLEMENTATION_STATUS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_STATUS_HEADER","title":"IMPLEMENTATION_STATUS_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_STATUS_REMARKS_HEADER","title":"IMPLEMENTATION_STATUS_REMARKS_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTED_REQUIREMENT","title":"IMPLEMENTED_REQUIREMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INHERITANCE_VIEW_DIR","title":"INHERITANCE_VIEW_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INHERITED_UUID","title":"INHERITED_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_FULL_HELP","title":"INIT_FULL_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_FULL_LONG","title":"INIT_FULL_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_FULL_SHORT","title":"INIT_FULL_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_GOVDOCS_HELP","title":"INIT_GOVDOCS_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_GOVDOCS_LONG","title":"INIT_GOVDOCS_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_GOVDOCS_SHORT","title":"INIT_GOVDOCS_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_LOCAL_HELP","title":"INIT_LOCAL_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_LOCAL_LONG","title":"INIT_LOCAL_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_LOCAL_SHORT","title":"INIT_LOCAL_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IOF_HELP","title":"IOF_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IOF_LONG","title":"IOF_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IOF_SHORT","title":"IOF_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ITEM","title":"ITEM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.LABEL","title":"LABEL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.LEVERAGED_SSP","title":"LEVERAGED_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.LEV_AUTH_UUID","title":"LEV_AUTH_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MARKDOWN_FILE_EXT","title":"MARKDOWN_FILE_EXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MARKDOWN_URL_REGEX","title":"MARKDOWN_URL_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MATCH_ALL_EXCEPT_LETTERS_UNDERSCORE_SPACE_REGEX","title":"MATCH_ALL_EXCEPT_LETTERS_UNDERSCORE_SPACE_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_A_PLAN","title":"MODEL_DIR_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_A_RESULT","title":"MODEL_DIR_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_CATALOG","title":"MODEL_DIR_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_COMPDEF","title":"MODEL_DIR_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_LIST","title":"MODEL_DIR_LIST","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_POAM","title":"MODEL_DIR_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_PROFILE","title":"MODEL_DIR_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_SSP","title":"MODEL_DIR_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_TO_MODEL_MODULE","title":"MODEL_DIR_TO_MODEL_MODULE","text":"

                                    Map of model type to oscal module.

                                    "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_A_PLAN","title":"MODEL_MODULE_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_A_RESULT","title":"MODEL_MODULE_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_CATALOG","title":"MODEL_MODULE_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_COMPDEF","title":"MODEL_MODULE_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_LIST","title":"MODEL_MODULE_LIST","text":"

                                    Map of plural form of a model type to the oscal module that contains the classes related to it.

                                    "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_POAM","title":"MODEL_MODULE_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_PROFILE","title":"MODEL_MODULE_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_SSP","title":"MODEL_MODULE_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_TO_MODEL_TYPE","title":"MODEL_MODULE_TO_MODEL_TYPE","text":"

                                    Map of model type to model directory.

                                    "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_A_PLAN","title":"MODEL_TYPE_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_A_RESULT","title":"MODEL_TYPE_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_CATALOG","title":"MODEL_TYPE_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_COMPDEF","title":"MODEL_TYPE_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_LIST","title":"MODEL_TYPE_LIST","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_POAM","title":"MODEL_TYPE_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_PROFILE","title":"MODEL_TYPE_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_SSP","title":"MODEL_TYPE_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_TO_MODEL_DIR","title":"MODEL_TYPE_TO_MODEL_DIR","text":"

                                    Element path separator

                                    "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_TO_MODEL_MODULE","title":"MODEL_TYPE_TO_MODEL_MODULE","text":"

                                    Map of model module to model type.

                                    "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_A_PLAN","title":"MODULE_NAME_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_A_RESULT","title":"MODULE_NAME_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_CATALOG","title":"MODULE_NAME_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_COMPDEF","title":"MODULE_NAME_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_POAM","title":"MODULE_NAME_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_PROFILE","title":"MODULE_NAME_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_SSP","title":"MODULE_NAME_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NAME","title":"NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NAMESPACE_FEDRAMP","title":"NAMESPACE_FEDRAMP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NAMESPACE_NIST","title":"NAMESPACE_NIST","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NCNAME_REGEX","title":"NCNAME_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NCNAME_UTF8_FIRST_CHAR_OPTIONS","title":"NCNAME_UTF8_FIRST_CHAR_OPTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NCNAME_UTF8_OTHER_CHAR_OPTIONS","title":"NCNAME_UTF8_OTHER_CHAR_OPTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.OBJECTIVE_PART","title":"OBJECTIVE_PART","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ONE","title":"ONE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ONE_OR_MORE_HYPHENED","title":"ONE_OR_MORE_HYPHENED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ONE_OR_MORE_SPACED","title":"ONE_OR_MORE_SPACED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_CUSTOMER_CONFIGURED","title":"ORIGINATION_CUSTOMER_CONFIGURED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_CUSTOMER_PROVIDED","title":"ORIGINATION_CUSTOMER_PROVIDED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_INHERITED","title":"ORIGINATION_INHERITED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_ORGANIZATION","title":"ORIGINATION_ORGANIZATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_SYSTEM_SPECIFIC","title":"ORIGINATION_SYSTEM_SPECIFIC","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PACKAGE_OSCAL","title":"PACKAGE_OSCAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAMETER_DESCRIPTION","title":"PARAMETER_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAMETER_ID","title":"PARAMETER_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAMETER_VALUE_ALTERNATIVES","title":"PARAMETER_VALUE_ALTERNATIVES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAM_VALUES_TAG","title":"PARAM_VALUES_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAM_VALUE_ORIGIN","title":"PARAM_VALUE_ORIGIN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PART_REGEX","title":"PART_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE","title":"PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT","title":"PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE_PARAM_VALUE_ORIGIN","title":"PROFILE_PARAM_VALUE_ORIGIN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE_VALUES","title":"PROFILE_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROPERTY_REGEX","title":"PROPERTY_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROVIDED_STATEMENT_DESCRIPTION","title":"PROVIDED_STATEMENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROVIDED_UUID","title":"PROVIDED_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.REMARKS","title":"REMARKS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.REPLACE_ME","title":"REPLACE_ME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.REPLACE_ME_PLACEHOLDER","title":"REPLACE_ME_PLACEHOLDER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESOLUTION_SOURCE","title":"RESOLUTION_SOURCE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBILITY_STATEMENT_DESCRIPTION","title":"RESPONSIBILITY_STATEMENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBILITY_UUID","title":"RESPONSIBILITY_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBLE_ROLE","title":"RESPONSIBLE_ROLE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBLE_ROLES","title":"RESPONSIBLE_ROLES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ROOT","title":"ROOT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULES_PARAMS_TAG","title":"RULES_PARAMS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULES_WARNING","title":"RULES_WARNING","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULE_DESCRIPTION","title":"RULE_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULE_ID","title":"RULE_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SAMPLE_UUID_STR","title":"SAMPLE_UUID_STR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SATISFIED_STATEMENT_COMMENT","title":"SATISFIED_STATEMENT_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SATISFIED_STATEMENT_DESCRIPTION","title":"SATISFIED_STATEMENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SECTIONS_TAG","title":"SECTIONS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SET_PARAMS_TAG","title":"SET_PARAMS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SFTP_URI","title":"SFTP_URI","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SORT_ID","title":"SORT_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT","title":"SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_FOR_ITEM_TEXT","title":"SSP_ADD_IMPLEMENTATION_FOR_ITEM_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_FOR_STATEMENT_TEXT","title":"SSP_ADD_IMPLEMENTATION_FOR_STATEMENT_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_PREFIX","title":"SSP_ADD_IMPLEMENTATION_PREFIX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT","title":"SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_FEDRAMP_TAG","title":"SSP_FEDRAMP_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MAIN_COMP_NAME","title":"SSP_MAIN_COMP_NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MD_HRULE_LINE","title":"SSP_MD_HRULE_LINE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MD_IMPLEMENTATION_QUESTION","title":"SSP_MD_IMPLEMENTATION_QUESTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MD_LEAVE_BLANK_TEXT","title":"SSP_MD_LEAVE_BLANK_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_SYSTEM_CONTROL_IMPLEMENTATION_TEXT","title":"SSP_SYSTEM_CONTROL_IMPLEMENTATION_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_VALUES","title":"SSP_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATEMENT","title":"STATEMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_ALL","title":"STATUS_ALL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_ALTERNATIVE","title":"STATUS_ALTERNATIVE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_COMPLETION_DATE","title":"STATUS_COMPLETION_DATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_DISPOSITION","title":"STATUS_DISPOSITION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_IMPLEMENTED","title":"STATUS_IMPLEMENTED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_INHERITED","title":"STATUS_INHERITED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_NOT_APPLICABLE","title":"STATUS_NOT_APPLICABLE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_OPERATIONAL","title":"STATUS_OPERATIONAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_OTHER","title":"STATUS_OTHER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PARTIAL","title":"STATUS_PARTIAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PARTIALLY_IMPLEMENTED","title":"STATUS_PARTIALLY_IMPLEMENTED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PLANNED","title":"STATUS_PLANNED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PLANNED_COMPLETION_DATE","title":"STATUS_PLANNED_COMPLETION_DATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PROMPT","title":"STATUS_PROMPT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_REMARKS","title":"STATUS_REMARKS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_UNDER_DEVELOPMENT","title":"STATUS_UNDER_DEVELOPMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_UNDER_MAJOR_MODIFICATION","title":"STATUS_UNDER_MAJOR_MODIFICATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TABLE_OF_PARAMS_PART","title":"TABLE_OF_PARAMS_PART","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TEMPLATE_VERSION_REGEX","title":"TEMPLATE_VERSION_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.THIS_SYSTEM_AS_KEY","title":"THIS_SYSTEM_AS_KEY","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.THIS_SYSTEM_PROMPT","title":"THIS_SYSTEM_PROMPT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TITLE","title":"TITLE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRANSFORM_TYPES","title":"TRANSFORM_TYPES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_ADD_PROPS_TAG","title":"TRESTLE_ADD_PROPS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_CACHE_DIR","title":"TRESTLE_CACHE_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_CONFIG_DIR","title":"TRESTLE_CONFIG_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_CONFIG_FILE","title":"TRESTLE_CONFIG_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_DIST_DIR","title":"TRESTLE_DIST_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_GENERIC_NS","title":"TRESTLE_GENERIC_NS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_GLOBAL_TAG","title":"TRESTLE_GLOBAL_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_HREF_HEADING","title":"TRESTLE_HREF_HEADING","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_HREF_REGEX","title":"TRESTLE_HREF_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_IMP_STATUS_TAG","title":"TRESTLE_IMP_STATUS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_INHERITED_PROPS_TAG","title":"TRESTLE_INHERITED_PROPS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_INHERITED_PROPS_TRACKER","title":"TRESTLE_INHERITED_PROPS_TRACKER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_KEEP_FILE","title":"TRESTLE_KEEP_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_LEVERAGING_COMP_TAG","title":"TRESTLE_LEVERAGING_COMP_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_PROPS_TAG","title":"TRESTLE_PROPS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_STATEMENT_TAG","title":"TRESTLE_STATEMENT_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_TAG","title":"TRESTLE_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.UNIX_CACHE_ROOT","title":"UNIX_CACHE_ROOT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.UUID_REGEX","title":"UUID_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VALUES","title":"VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VALUE_ASSIGNED_PREFIX","title":"VALUE_ASSIGNED_PREFIX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VALUE_NOT_ASSIGNED_PREFIX","title":"VALUE_NOT_ASSIGNED_PREFIX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_ALL","title":"VAL_MODE_ALL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_CATALOG","title":"VAL_MODE_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_DUPLICATES","title":"VAL_MODE_DUPLICATES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_LINKS","title":"VAL_MODE_LINKS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_REFS","title":"VAL_MODE_REFS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_RULES","title":"VAL_MODE_RULES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WEBSITE_ROOT","title":"WEBSITE_ROOT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WINDOWS_DRIVE_LETTER_REGEX","title":"WINDOWS_DRIVE_LETTER_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WINDOWS_DRIVE_URI_REGEX","title":"WINDOWS_DRIVE_URI_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WINDOWS_PLATFORM_STR","title":"WINDOWS_PLATFORM_STR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_LEVERAGED_COMMENT","title":"YAML_LEVERAGED_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_LEVERAGING_COMP_COMMENT","title":"YAML_LEVERAGING_COMP_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_PROFILE_VALUES_COMMENT","title":"YAML_PROFILE_VALUES_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_PROPS_COMMENT","title":"YAML_PROPS_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT","title":"YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_RULE_PARAM_VALUES_SSP_COMMENT","title":"YAML_RULE_PARAM_VALUES_SSP_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_SSP_VALUES_COMMENT","title":"YAML_SSP_VALUES_COMMENT","text":""},{"location":"api_reference/trestle.common.err/","title":"err","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err","title":"trestle.common.err","text":"

                                    Trestle core errors module.

                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError","title":" TrestleError (RuntimeError) ","text":"

                                    General framework (non-application) related errors.

                                    Attributes:

                                    Name Type Description msg str

                                    Human readable string describing the exception.

                                    Source code in trestle/common/err.py
                                    class TrestleError(RuntimeError):\n\"\"\"\n    General framework (non-application) related errors.\n\n    Attributes:\n        msg (str): Human readable string describing the exception.\n    \"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"Intialization for TresleError.\n\n        Args:\n            msg (str): The error message\n        \"\"\"\n        RuntimeError.__init__(self)\n        self.msg = msg\n\n    def __str__(self) -> str:\n\"\"\"Return Trestle error message if asked for a string.\"\"\"\n        return self.msg\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError.__init__","title":"__init__(self, msg) special","text":"

                                    Intialization for TresleError.

                                    Parameters:

                                    Name Type Description Default msg str

                                    The error message

                                    required Source code in trestle/common/err.py
                                    def __init__(self, msg: str):\n\"\"\"Intialization for TresleError.\n\n    Args:\n        msg (str): The error message\n    \"\"\"\n    RuntimeError.__init__(self)\n    self.msg = msg\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError.__str__","title":"__str__(self) special","text":"

                                    Return Trestle error message if asked for a string.

                                    Source code in trestle/common/err.py
                                    def __str__(self) -> str:\n\"\"\"Return Trestle error message if asked for a string.\"\"\"\n    return self.msg\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleIncorrectArgsError","title":" TrestleIncorrectArgsError (TrestleError) ","text":"

                                    General error for incorrect args passed to Trestle command.

                                    Source code in trestle/common/err.py
                                    class TrestleIncorrectArgsError(TrestleError):\n\"\"\"General error for incorrect args passed to Trestle command.\"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"\n        Initialize TrestleIncorrectArgsError.\n\n        Args:\n            msg (str): The error message\n        \"\"\"\n        super().__init__(msg)\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleIncorrectArgsError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleIncorrectArgsError.__init__","title":"__init__(self, msg) special","text":"

                                    Initialize TrestleIncorrectArgsError.

                                    Parameters:

                                    Name Type Description Default msg str

                                    The error message

                                    required Source code in trestle/common/err.py
                                    def __init__(self, msg: str):\n\"\"\"\n    Initialize TrestleIncorrectArgsError.\n\n    Args:\n        msg (str): The error message\n    \"\"\"\n    super().__init__(msg)\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleNotFoundError","title":" TrestleNotFoundError (TrestleError) ","text":"

                                    General framework related not found error.

                                    Attributes:

                                    Name Type Description msg str

                                    Human readable string describing the exception.

                                    Source code in trestle/common/err.py
                                    class TrestleNotFoundError(TrestleError):\n\"\"\"\n    General framework related not found error.\n\n    Attributes:\n        msg (str): Human readable string describing the exception.\n    \"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"\n        Intialize TresleNotFoundError.\n\n        Args:\n            msg: The error message\n        \"\"\"\n        super().__init__(msg)\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleNotFoundError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleNotFoundError.__init__","title":"__init__(self, msg) special","text":"

                                    Intialize TresleNotFoundError.

                                    Parameters:

                                    Name Type Description Default msg str

                                    The error message

                                    required Source code in trestle/common/err.py
                                    def __init__(self, msg: str):\n\"\"\"\n    Intialize TresleNotFoundError.\n\n    Args:\n        msg: The error message\n    \"\"\"\n    super().__init__(msg)\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleRootError","title":" TrestleRootError (TrestleError) ","text":"

                                    General error for trestle workspace root/setup errors.

                                    Source code in trestle/common/err.py
                                    class TrestleRootError(TrestleError):\n\"\"\"General error for trestle workspace root/setup errors.\"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"\n        Initialize TrestleRootError.\n\n        Args:\n            msg (str): The error message\n        \"\"\"\n        super().__init__(msg)\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleRootError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleRootError.__init__","title":"__init__(self, msg) special","text":"

                                    Initialize TrestleRootError.

                                    Parameters:

                                    Name Type Description Default msg str

                                    The error message

                                    required Source code in trestle/common/err.py
                                    def __init__(self, msg: str):\n\"\"\"\n    Initialize TrestleRootError.\n\n    Args:\n        msg (str): The error message\n    \"\"\"\n    super().__init__(msg)\n
                                    "},{"location":"api_reference/trestle.common.err/#trestle.common.err-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.handle_generic_command_exception","title":"handle_generic_command_exception(exception, logger, msg='Exception occured during execution')","text":"

                                    Print out error message based on the verbosity and return appropriate status code.

                                    Source code in trestle/common/err.py
                                    def handle_generic_command_exception(\n    exception: Exception, logger: Logger, msg: str = 'Exception occured during execution'\n) -> int:\n\"\"\"Print out error message based on the verbosity and return appropriate status code.\"\"\"\n    if get_current_verbosity_level(logger) == 0:\n        logger.error(msg + f': {exception}')\n    else:\n        logger.exception(msg + f': {exception}')\n\n    return _exception_to_error_code(exception)\n
                                    "},{"location":"api_reference/trestle.common.file_utils/","title":"file_utils","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils","title":"trestle.common.file_utils","text":"

                                    Trestle file system utils.

                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.check_oscal_directories","title":"check_oscal_directories(root_path)","text":"

                                    Identify the state of the trestle workspace.

                                    Traverses trestle workspace and looks for unexpected files or directories. Additional files are allowed in the Trestle root but not inside the model folders.

                                    Source code in trestle/common/file_utils.py
                                    def check_oscal_directories(root_path: pathlib.Path) -> bool:\n\"\"\"\n    Identify the state of the trestle workspace.\n\n    Traverses trestle workspace and looks for unexpected files or directories.\n    Additional files are allowed in the Trestle root but not inside the model folders.\n    \"\"\"\n    trestle_dir_walk = os.walk(root_path)\n    is_valid = True\n\n    for _, dirs, _ in trestle_dir_walk:\n        for d in dirs:\n            if d in MODEL_DIR_LIST:\n                is_valid = _verify_oscal_folder(root_path / d)\n                if not is_valid:\n                    break\n    return is_valid\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.extract_project_model_path","title":"extract_project_model_path(path)","text":"

                                    Get the base path of the trestle model project.

                                    Source code in trestle/common/file_utils.py
                                    def extract_project_model_path(path: pathlib.Path) -> Optional[pathlib.Path]:\n\"\"\"Get the base path of the trestle model project.\"\"\"\n    if len(path.parts) > 2:\n        for i in range(2, len(path.parts)):\n            current = pathlib.Path(path.parts[0]).joinpath(*path.parts[1:i + 1])\n            if _is_valid_project_model_path(current):\n                return current\n    return None\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.extract_trestle_project_root","title":"extract_trestle_project_root(path)","text":"

                                    Get the trestle workspace root folder in the path.

                                    Source code in trestle/common/file_utils.py
                                    def extract_trestle_project_root(path: pathlib.Path) -> Optional[pathlib.Path]:\n\"\"\"Get the trestle workspace root folder in the path.\"\"\"\n    while len(path.parts) > 1:  # it must not be the system root directory\n        if is_valid_project_root(path):\n            return path\n        path = path.parent\n    return None\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.get_contextual_file_type","title":"get_contextual_file_type(path)","text":"

                                    Return the file content type for files in the given directory, if it's a trestle workspace.

                                    Source code in trestle/common/file_utils.py
                                    def get_contextual_file_type(path: pathlib.Path) -> FileContentType:\n\"\"\"Return the file content type for files in the given directory, if it's a trestle workspace.\"\"\"\n    if not _is_valid_project_model_path(path):\n        raise err.TrestleError(f'Trestle workspace not found at path {path}')\n\n    for file_or_directory in iterdir_without_hidden_files(path):\n        if file_or_directory.is_file():\n            return FileContentType.to_content_type(file_or_directory.suffix)\n\n    for file_or_directory in path.iterdir():\n        if file_or_directory.is_dir():\n            return get_contextual_file_type(file_or_directory)\n\n    raise err.TrestleError('No files found in the project.')\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.insert_text_in_file","title":"insert_text_in_file(file_path, tag, text)","text":"

                                    Insert text lines after line containing tag.

                                    Return True on success, False tag not found. Text is a string with appropriate \\n line endings. If tag is none just add at end of file. This will only open file once if tag is not found.

                                    Source code in trestle/common/file_utils.py
                                    def insert_text_in_file(file_path: pathlib.Path, tag: Optional[str], text: str) -> bool:\nr\"\"\"Insert text lines after line containing tag.\n\n    Return True on success, False tag not found.\n    Text is a string with appropriate \\n line endings.\n    If tag is none just add at end of file.\n    This will only open file once if tag is not found.\n    \"\"\"\n    if not file_path.exists():\n        raise TrestleError(f'Test file {file_path} not found.')\n    if tag:\n        lines: List[str] = []\n        with file_path.open('r', encoding=const.FILE_ENCODING) as f:\n            lines = f.readlines()\n        for ii, line in enumerate(lines):\n            if line.find(tag) >= 0:\n                lines.insert(ii + 1, text)\n                with file_path.open('w', encoding=const.FILE_ENCODING) as f:\n                    f.writelines(lines)\n                return True\n    else:\n        with file_path.open('a', encoding=const.FILE_ENCODING) as f:\n            f.writelines(text)\n        return True\n    return False\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_directory_name_allowed","title":"is_directory_name_allowed(name)","text":"

                                    Determine whether a directory name, which is a 'non-core-OSCAL activity/directory is allowed.

                                    Parameters:

                                    Name Type Description Default name str

                                    the name which is assumed may take the form of a relative path for task/subtasks.

                                    required

                                    Returns:

                                    Type Description bool

                                    Whether the name is allowed or not allowed (interferes with assumed project directories such as catalogs).

                                    Source code in trestle/common/file_utils.py
                                    def is_directory_name_allowed(name: str) -> bool:\n\"\"\"Determine whether a directory name, which is a 'non-core-OSCAL activity/directory is allowed.\n\n    args:\n        name: the name which is assumed may take the form of a relative path for task/subtasks.\n\n    Returns:\n        Whether the name is allowed or not allowed (interferes with assumed project directories such as catalogs).\n    \"\"\"\n    # Task must not use an OSCAL directory\n    # Task must not self-interfere with a project\n    pathed_name = pathlib.Path(name)\n\n    root_path = pathed_name.parts[0]\n    if root_path in const.MODEL_TYPE_TO_MODEL_DIR.values():\n        logger.warning('Task name is the same as an OSCAL schema name.')\n        return False\n    if root_path[0] == '.':\n        logger.warning('Task name must not start with \".\"')\n        return False\n    if pathed_name.suffix != '':\n        # Does it look like a file\n        logger.warning('Task name must not look like a file path (e.g. contain a suffix')\n        return False\n    if '__global__' in pathed_name.parts:\n        logger.warning('Task name cannot contain __global__')\n        return False\n    return True\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_hidden","title":"is_hidden(file_path)","text":"

                                    Determine whether a file is hidden based on the appropriate os attributes.

                                    This function will only work for the current file path only (e.g. not if a parent is hidden).

                                    Parameters:

                                    Name Type Description Default file_path Path

                                    The file path for which we are testing whether the file / directory is hidden.

                                    required

                                    Returns:

                                    Type Description bool

                                    Whether or not the file is file/directory is hidden.

                                    Source code in trestle/common/file_utils.py
                                    def is_hidden(file_path: pathlib.Path) -> bool:\n\"\"\"\n    Determine whether a file is hidden based on the appropriate os attributes.\n\n    This function will only work for the current file path only (e.g. not if a parent is hidden).\n\n    Args:\n        file_path: The file path for which we are testing whether the file / directory is hidden.\n\n    Returns:\n        Whether or not the file is file/directory is hidden.\n    \"\"\"\n    # as far as trestle is concerned all .* files are hidden even on windows, regardless of attributes\n    if file_path.stem.startswith('.'):\n        return True\n    # Handle windows\n    if is_windows():  # pragma: no cover\n        attribute = win32api.GetFileAttributes(str(file_path))\n        return attribute & (win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM)\n    return False\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_local_and_visible","title":"is_local_and_visible(file_path)","text":"

                                    Is the file or dir local (not a symlink) and not hidden.

                                    Source code in trestle/common/file_utils.py
                                    def is_local_and_visible(file_path: pathlib.Path) -> bool:\n\"\"\"Is the file or dir local (not a symlink) and not hidden.\"\"\"\n    return not (is_hidden(file_path) or is_symlink(file_path))\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_symlink","title":"is_symlink(file_path)","text":"

                                    Is the file path a symlink.

                                    Source code in trestle/common/file_utils.py
                                    def is_symlink(file_path: pathlib.Path) -> bool:\n\"\"\"Is the file path a symlink.\"\"\"\n    if is_windows():\n        return file_path.suffix == '.lnk'\n    return file_path.is_symlink()\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_valid_project_root","title":"is_valid_project_root(path)","text":"

                                    Check if the path is a valid trestle workspace root.

                                    Source code in trestle/common/file_utils.py
                                    def is_valid_project_root(path: pathlib.Path) -> bool:\n\"\"\"Check if the path is a valid trestle workspace root.\"\"\"\n    trestle_dir = path / const.TRESTLE_CONFIG_DIR\n    return trestle_dir.exists() and trestle_dir.is_dir()\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_windows","title":"is_windows()","text":"

                                    Check if current operating system is Windows.

                                    Source code in trestle/common/file_utils.py
                                    def is_windows() -> bool:\n\"\"\"Check if current operating system is Windows.\"\"\"\n    return platform.system() == const.WINDOWS_PLATFORM_STR\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.iterdir_without_hidden_files","title":"iterdir_without_hidden_files(directory_path)","text":"

                                    Get iterator over all paths in the given directory_path excluding hidden files.

                                    Parameters:

                                    Name Type Description Default directory_path Path

                                    The directory to iterate through.

                                    required

                                    Returns:

                                    Type Description Iterable[pathlib.Path]

                                    Iterator over the files in the directory excluding hidden files.

                                    Source code in trestle/common/file_utils.py
                                    def iterdir_without_hidden_files(directory_path: pathlib.Path) -> Iterable[pathlib.Path]:\n\"\"\"\n    Get iterator over all paths in the given directory_path excluding hidden files.\n\n    Args:\n        directory_path: The directory to iterate through.\n\n    Returns:\n        Iterator over the files in the directory excluding hidden files.\n    \"\"\"\n    filtered_paths = list(filter(lambda p: not is_hidden(p) or p.is_dir(), pathlib.Path.iterdir(directory_path)))\n\n    return filtered_paths.__iter__()\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.load_file","title":"load_file(file_path)","text":"

                                    Load JSON or YAML file content into a dict.

                                    This is not intended to be the default load mechanism. It should only be used if a OSCAL object type is unknown but the context a user is in.

                                    Source code in trestle/common/file_utils.py
                                    def load_file(file_path: pathlib.Path) -> Dict[str, Any]:\n\"\"\"\n    Load JSON or YAML file content into a dict.\n\n    This is not intended to be the default load mechanism. It should only be used\n    if a OSCAL object type is unknown but the context a user is in.\n    \"\"\"\n    content_type = FileContentType.to_content_type(file_path.suffix)\n    with file_path.open('r', encoding=const.FILE_ENCODING) as f:\n        if content_type == FileContentType.YAML:\n            yaml = YAML(typ='safe')\n            return yaml.load(f)\n        if content_type == FileContentType.JSON:\n            return json.load(f)\n    return {}\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.make_hidden_file","title":"make_hidden_file(file_path)","text":"

                                    Make hidden file.

                                    Source code in trestle/common/file_utils.py
                                    def make_hidden_file(file_path: pathlib.Path) -> None:\n\"\"\"Make hidden file.\"\"\"\n    if not file_path.name.startswith('.') and not is_windows():\n        file_path = file_path.parent / ('.' + file_path.name)\n\n    file_path.touch()\n    if is_windows():\n        atts = win32api.GetFileAttributes(str(file_path))\n        win32api.SetFileAttributes(str(file_path), win32con.FILE_ATTRIBUTE_HIDDEN | atts)\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.prune_empty_dirs","title":"prune_empty_dirs(file_path, pattern)","text":"

                                    Remove directories with no subdirs and with no files matching pattern.

                                    Source code in trestle/common/file_utils.py
                                    def prune_empty_dirs(file_path: pathlib.Path, pattern: str) -> None:\n\"\"\"Remove directories with no subdirs and with no files matching pattern.\"\"\"\n    deleted: Set[str] = set()\n    # this traverses from leaf nodes upward so only needs one traversal\n    for current_dir, subdirs, _ in os.walk(str(file_path), topdown=False):\n        true_dirs = [subdir for subdir in subdirs if os.path.join(current_dir, subdir) not in deleted]\n        if not true_dirs and not any(glob.glob(f'{current_dir}/{pattern}')):\n            shutil.rmtree(current_dir)\n            deleted.add(current_dir)\n
                                    "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.relative_resolve","title":"relative_resolve(candidate, cwd)","text":"

                                    Resolve a candidate file path relative to a provided cwd.

                                    This is to circumvent bad behaviour for resolve on windows platforms where the path must exist.

                                    If a relative dir is passed it presumes the directory is relative to the PROVIDED cwd. If relative expansions exist (e.g. ../) the final result must still be within the cwd.

                                    If an absolute path is provided it tests whether the path is within the cwd or not.

                                    Source code in trestle/common/file_utils.py
                                    def relative_resolve(candidate: pathlib.Path, cwd: pathlib.Path) -> pathlib.Path:\n\"\"\"Resolve a candidate file path relative to a provided cwd.\n\n    This is to circumvent bad behaviour for resolve on windows platforms where the path must exist.\n\n    If a relative dir is passed it presumes the directory is relative to the PROVIDED cwd.\n    If relative expansions exist (e.g. ../) the final result must still be within the cwd.\n\n    If an absolute path is provided it tests whether the path is within the cwd or not.\n\n    \"\"\"\n    # Expand user first if applicable.\n    candidate = candidate.expanduser()\n\n    if not cwd.is_absolute():\n        raise TrestleError('Error handling current working directory. CWD is expected to be absolute.')\n\n    if not candidate.is_absolute():\n        new = pathlib.Path(cwd / candidate).resolve()\n    else:\n        new = candidate.resolve()\n    try:\n        new.relative_to(cwd)\n    except ValueError:\n        raise TrestleError(f'Provided dir {candidate} is not relative to {cwd}')\n    return new\n
                                    "},{"location":"api_reference/trestle.common.list_utils/","title":"list_utils","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils","title":"trestle.common.list_utils","text":"

                                    Trestle List Utils.

                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.as_dict","title":"as_dict(dict_or_none)","text":"

                                    Convert dict or None object to itself or an empty dict if none.

                                    Source code in trestle/common/list_utils.py
                                    def as_dict(dict_or_none: Optional[Dict[TG, TG2]]) -> Dict[TG, TG2]:\n\"\"\"Convert dict or None object to itself or an empty dict if none.\"\"\"\n    return dict_or_none if dict_or_none else {}\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.as_filtered_list","title":"as_filtered_list(list_or_none, filter_condition)","text":"

                                    Convert to list and filter based on the condition.

                                    Source code in trestle/common/list_utils.py
                                    def as_filtered_list(list_or_none: Optional[List[TG]], filter_condition: Callable[[TG], bool]) -> List[TG]:\n\"\"\"Convert to list and filter based on the condition.\"\"\"\n    result_list = as_list(list_or_none)\n    result_list = list(filter(filter_condition, result_list))\n    return result_list\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.as_list","title":"as_list(list_or_none)","text":"

                                    Convert list or None object to itself or an empty list if none.

                                    Source code in trestle/common/list_utils.py
                                    def as_list(list_or_none: Optional[List[TG]]) -> List[TG]:\n\"\"\"Convert list or None object to itself or an empty list if none.\"\"\"\n    return list_or_none if list_or_none else []\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.comma_colon_sep_to_dict","title":"comma_colon_sep_to_dict(string_or_none)","text":"

                                    Convert optional comma and colon-sep list to dict.

                                    Source code in trestle/common/list_utils.py
                                    def comma_colon_sep_to_dict(string_or_none: Optional[str]) -> Dict[str, str]:\n\"\"\"Convert optional comma and colon-sep list to dict.\"\"\"\n    entries = comma_sep_to_list(string_or_none)\n    dic = {}\n    for entry in entries:\n        # if more than one colon include any colons in the value after the first one\n        token = entry.split(':', 1)\n        if len(token) == 1:\n            dic[token[0].strip()] = token[0].strip()\n        else:\n            dic[token[0].strip()] = token[1].strip()\n    return dic\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.comma_sep_to_list","title":"comma_sep_to_list(string_or_none)","text":"

                                    Convert optional comma-sep string to list of strings and strip.

                                    Source code in trestle/common/list_utils.py
                                    def comma_sep_to_list(string_or_none: Optional[str]) -> List[str]:\n\"\"\"Convert optional comma-sep string to list of strings and strip.\"\"\"\n    string_or_none = string_or_none.strip() if string_or_none else None\n    return list(map(str.strip, string_or_none.split(','))) if string_or_none else []\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_append","title":"deep_append(dic, path, value)","text":"

                                    Append to list in dict.

                                    Source code in trestle/common/list_utils.py
                                    def deep_append(dic: Dict[str, Any], path: List[str], value: Any) -> None:\n\"\"\"Append to list in dict.\"\"\"\n    if not path:\n        raise TrestleError('Error appending value in deep append with empty path.')\n    for node in path[:-1]:\n        dic[node] = dic.get(node, {})\n        dic = dic[node]\n    if path[-1] not in dic:\n        dic[path[-1]] = []\n    dic[path[-1]].append(value)\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_get","title":"deep_get(dic, path, default=None)","text":"

                                    Get value from deep in dictionary.

                                    Source code in trestle/common/list_utils.py
                                    def deep_get(dic: Dict[str, Any], path: List[str], default: Any = None) -> Any:\n\"\"\"Get value from deep in dictionary.\"\"\"\n    if not path:\n        raise TrestleError('Error getting value in deep get with empty path.')\n    for node in path[:-1]:\n        if node not in dic:\n            return default\n        dic = dic[node]\n    return dic.get(path[-1], default)\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_set","title":"deep_set(dic, path, value, pop_if_none=True)","text":"

                                    Set value deep in dictionary.

                                    pop_if_none will cause the key to be removed if value is None

                                    Source code in trestle/common/list_utils.py
                                    def deep_set(dic: Dict[str, Any], path: List[str], value: Any, pop_if_none: bool = True) -> None:\n\"\"\"\n    Set value deep in dictionary.\n\n    pop_if_none will cause the key to be removed if value is None\n    \"\"\"\n    if not path:\n        raise TrestleError('Error setting value in deep set with empty path.')\n    for node in path[:-1]:\n        dic[node] = dic.get(node, {})\n        dic = dic[node]\n    if value or not pop_if_none:\n        dic[path[-1]] = value\n    else:\n        dic.pop(path[-1], None)\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_update","title":"deep_update(dic, path, dic_value)","text":"

                                    Update the dict based on path.

                                    Source code in trestle/common/list_utils.py
                                    def deep_update(dic: Dict[str, Any], path: List[str], dic_value: Dict[str, Any]) -> None:\n\"\"\"Update the dict based on path.\"\"\"\n    if not path:\n        raise TrestleError('Error updating value in deep update with empty path.')\n    for node in path:\n        dic[node] = dic.get(node, {})\n        dic = dic[node]\n    dic.update(dic_value)\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.delete_item_from_list","title":"delete_item_from_list(item_list, value, key)","text":"

                                    Remove the first matching item if it is present in a list based on the callable key matching the query value.

                                    Source code in trestle/common/list_utils.py
                                    def delete_item_from_list(item_list: List[TG], value: TG2, key: Callable[[TG], TG2]) -> List[TG]:\n\"\"\"Remove the first matching item if it is present in a list based on the callable key matching the query value.\"\"\"\n    keys = [key(item) for item in item_list]\n    if value in keys:\n        index = keys.index(value)\n        del item_list[index]\n    return item_list\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.delete_list_from_list","title":"delete_list_from_list(item_list, indices)","text":"

                                    Delete a list of items from a list based on indices.

                                    Source code in trestle/common/list_utils.py
                                    def delete_list_from_list(item_list: List[TG], indices: List[int]) -> None:\n\"\"\"Delete a list of items from a list based on indices.\"\"\"\n    for index in sorted(indices, reverse=True):\n        del item_list[index]\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.get_default","title":"get_default(item, default)","text":"

                                    Return the default value for the item if it is not set.

                                    Source code in trestle/common/list_utils.py
                                    def get_default(item: TG, default: TG) -> TG:\n\"\"\"Return the default value for the item if it is not set.\"\"\"\n    return item if item else default\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.get_item_from_list","title":"get_item_from_list(item_list, value, key, remove=False)","text":"

                                    Get first item from list if present based on key matching value with option to remove it from the list.

                                    Source code in trestle/common/list_utils.py
                                    def get_item_from_list(item_list: Optional[List[TG]],\n                       value: TG2,\n                       key: Callable[[TG], TG2],\n                       remove: bool = False) -> Optional[TG]:\n\"\"\"Get first item from list if present based on key matching value with option to remove it from the list.\"\"\"\n    if not item_list:\n        return None\n    keys = [key(item) for item in item_list]\n    item = None\n    if value in keys:\n        index = keys.index(value)\n        item = item_list[index]\n        if remove:\n            del item_list[index]\n    return item\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.is_ordered_sublist","title":"is_ordered_sublist(needle, haystack)","text":"

                                    Determine if needle is exactly contained in haystack.

                                    The needle list comprises an ordered list of strings. The haystack list comprises an ordered list of strings that is to be searched. If the strings in the needle appear in the haystack in that exact order then return true, else false.

                                    Examples:

                                    needle=['a','b','c'], haystack=['x','y','a','b','c','z'], result = True needle=['a','b','c'], haystack=['x','y','a','b','z','c'], result = False

                                    Source code in trestle/common/list_utils.py
                                    def is_ordered_sublist(needle: List[str], haystack: List[str]) -> bool:\n\"\"\"Determine if needle is exactly contained in haystack.\n\n    The needle list comprises an ordered list of strings.\n    The haystack list comprises an ordered list of strings that is to be searched.\n    If the strings in the needle appear in the haystack in that exact order then\n    return true, else false.\n\n    Examples:\n    needle=['a','b','c'], haystack=['x','y','a','b','c','z'], result = True\n    needle=['a','b','c'], haystack=['x','y','a','b','z','c'], result = False\n    \"\"\"\n    return ' '.join(needle) in ' '.join(haystack)\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.join_key_to_list_dicts","title":"join_key_to_list_dicts(dict1, dict2)","text":"

                                    Join two dicts of str to List.

                                    Source code in trestle/common/list_utils.py
                                    def join_key_to_list_dicts(dict1: Dict[str, List[Any]], dict2: Dict[str, List[Any]]) -> Dict[str, List[Any]]:\n\"\"\"Join two dicts of str to List.\"\"\"\n    # merge like keys\n    dict3 = {key: dict1[key] + dict2.get(key, []) for key in dict1}\n    # merge unlike keys\n    dict3.update({key: dict2[key] for key in dict2 if key not in dict3})\n    return dict3\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.merge_dicts","title":"merge_dicts(dest, src)","text":"

                                    Merge the two dicts with priority to src.

                                    Source code in trestle/common/list_utils.py
                                    def merge_dicts(dest: Optional[Dict[str, str]], src: Optional[Dict[str, str]]) -> Dict[str, str]:\n\"\"\"Merge the two dicts with priority to src.\"\"\"\n    return {**as_dict(dest), **as_dict(src)}\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.none_if_empty","title":"none_if_empty(list_)","text":"

                                    Convert to None if empty list.

                                    Source code in trestle/common/list_utils.py
                                    def none_if_empty(list_: List[TG]) -> Optional[List[TG]]:\n\"\"\"Convert to None if empty list.\"\"\"\n    return list_ if list_ else None\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.pop_item_from_list","title":"pop_item_from_list(item_list, value, key)","text":"

                                    Pop first matching item from a list if it is present based on the key matching the value.

                                    Source code in trestle/common/list_utils.py
                                    def pop_item_from_list(item_list: Optional[List[TG]], value: TG2, key: Callable[[TG], TG2]) -> Optional[TG]:\n\"\"\"Pop first matching item from a list if it is present based on the key matching the value.\"\"\"\n    return get_item_from_list(item_list, value, key, True)\n
                                    "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.set_or_pop","title":"set_or_pop(dic, key, value)","text":"

                                    Set if value is non-empty list or not None otherwise remove.

                                    Source code in trestle/common/list_utils.py
                                    def set_or_pop(dic: Dict[str, Any], key: str, value: Any) -> None:\n\"\"\"Set if value is non-empty list or not None otherwise remove.\"\"\"\n    if value:\n        dic[key] = value\n    else:\n        dic.pop(key, None)\n
                                    "},{"location":"api_reference/trestle.common.load_validate/","title":"load_validate","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate","title":"trestle.common.load_validate","text":"

                                    Function to load and validate files while avoiding circular imports.

                                    "},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate.load_validate_model_name","title":"load_validate_model_name(trestle_root, model_name, model_class, file_content_type=None)","text":"

                                    Load a model by its name and type and validate it.

                                    Source code in trestle/common/load_validate.py
                                    def load_validate_model_name(\n    trestle_root: Path,\n    model_name: str,\n    model_class: TG,\n    file_content_type: Optional[FileContentType] = None\n) -> Tuple[TG, Path]:\n\"\"\"Load a model by its name and type and validate it.\"\"\"\n    model_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, model_name, model_class, file_content_type)\n    model = load_validate_model_path(trestle_root, model_path)\n    return model, model_path\n
                                    "},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate.load_validate_model_path","title":"load_validate_model_path(trestle_root, model_path)","text":"

                                    Load a model by its path and validate it.

                                    Source code in trestle/common/load_validate.py
                                    def load_validate_model_path(trestle_root: Path, model_path: Path) -> TopLevelOscalModel:\n\"\"\"Load a model by its path and validate it.\"\"\"\n    _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n    args = argparse.Namespace(mode=const.VAL_MODE_ALL, quiet=True)\n    validator: Validator = validator_factory.get(args)\n    if not validator.model_is_valid(model, True, trestle_root):\n        logger.warning(f'Model loaded at {model_path} fails validation, but is being loaded anyway.')\n    return model\n
                                    "},{"location":"api_reference/trestle.common.log/","title":"log","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log","title":"trestle.common.log","text":"

                                    Common logging utilities.

                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter","title":" SpecificLevelFilter (Filter) ","text":"

                                    Filter for the same level as provided by setLevel for a log handler.

                                    Python by default logs all levels above to a given destination. This makes it easy to split levels where you might log all levels to file and only errors to std.err, however, does not allow logging a specific level elsewhere.

                                    Source code in trestle/common/log.py
                                    class SpecificLevelFilter(logging.Filter):\n\"\"\"\n    Filter for the same level as provided by setLevel for a log handler.\n\n    Python by default logs all levels above to a given destination. This makes it easy to split levels where you might\n    log all levels to file and only errors to std.err, however, does not allow logging a specific level elsewhere.\n    \"\"\"\n\n    def __init__(self, level: int) -> None:\n\"\"\"Initialize providing maximum level to be pushed through the filter.\"\"\"\n        self._level = level\n\n    def filter(self, log_record: logging.LogRecord) -> bool:  # noqa: A003\n\"\"\"Filter log messages.\"\"\"\n        return log_record.levelno == self._level\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter.__init__","title":"__init__(self, level) special","text":"

                                    Initialize providing maximum level to be pushed through the filter.

                                    Source code in trestle/common/log.py
                                    def __init__(self, level: int) -> None:\n\"\"\"Initialize providing maximum level to be pushed through the filter.\"\"\"\n    self._level = level\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter.filter","title":"filter(self, log_record)","text":"

                                    Filter log messages.

                                    Source code in trestle/common/log.py
                                    def filter(self, log_record: logging.LogRecord) -> bool:  # noqa: A003\n\"\"\"Filter log messages.\"\"\"\n    return log_record.levelno == self._level\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace","title":" Trace ","text":"

                                    Class allowing low priority trace message when verbose > 1 and log level below DEBUG.

                                    Source code in trestle/common/log.py
                                    class Trace():\n\"\"\"Class allowing low priority trace message when verbose > 1 and log level below DEBUG.\"\"\"\n\n    def __init__(self, logger: logging.Logger) -> None:\n\"\"\"Store the main logger with its module name.\"\"\"\n        self._logger = logger\n\n    def log(self, msg: str) -> None:\n\"\"\"Output the trace msg if log level is below DEBUG.\"\"\"\n        level = self._logger.getEffectiveLevel()\n        if level < logging.DEBUG:\n            self._logger.debug(msg)\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace.__init__","title":"__init__(self, logger) special","text":"

                                    Store the main logger with its module name.

                                    Source code in trestle/common/log.py
                                    def __init__(self, logger: logging.Logger) -> None:\n\"\"\"Store the main logger with its module name.\"\"\"\n    self._logger = logger\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace.log","title":"log(self, msg)","text":"

                                    Output the trace msg if log level is below DEBUG.

                                    Source code in trestle/common/log.py
                                    def log(self, msg: str) -> None:\n\"\"\"Output the trace msg if log level is below DEBUG.\"\"\"\n    level = self._logger.getEffectiveLevel()\n    if level < logging.DEBUG:\n        self._logger.debug(msg)\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.get_current_verbosity_level","title":"get_current_verbosity_level(logger)","text":"

                                    Get the current verbosity level based on logging level.

                                    Source code in trestle/common/log.py
                                    def get_current_verbosity_level(logger: logging.Logger) -> int:\n\"\"\"Get the current verbosity level based on logging level.\"\"\"\n    level = logger.getEffectiveLevel()\n    if level < logging.DEBUG:\n        return 2\n    elif level == logging.DEBUG:\n        return 1\n    return 0\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log.set_global_logging_levels","title":"set_global_logging_levels(level=20)","text":"

                                    Initialise logging.

                                    Should only be invoked by the CLI classes or similar.

                                    Source code in trestle/common/log.py
                                    def set_global_logging_levels(level: int = logging.INFO) -> None:\n\"\"\"Initialise logging.\n\n    Should only be invoked by the CLI classes or similar.\n    \"\"\"\n    # This line stops default root loggers setup for a python context from logging extra messages.\n    # DO NOT USE THIS COMMAND directly from an SDK. Handle logs levels based on your own application\n    _logger.propagate = False\n    # Remove handlers\n    _logger.handlers.clear()\n    # set global level\n    _logger.setLevel(level)\n    # Create standard out\n    console_out_handler = logging.StreamHandler(sys.stdout)\n    console_out_handler.setLevel(logging.INFO)\n    console_out_handler.addFilter(SpecificLevelFilter(logging.INFO))\n\n    console_debug_handler = logging.StreamHandler(sys.stdout)\n    console_debug_handler.setLevel(logging.DEBUG)\n    console_debug_handler.addFilter(SpecificLevelFilter(logging.DEBUG))\n\n    console_error_handler = logging.StreamHandler(sys.stderr)\n    console_error_handler.setLevel(logging.WARNING)\n    # create formatters\n    error_formatter = logging.Formatter('%(name)s:%(lineno)d %(levelname)s: %(message)s')\n    debug_formatter = logging.Formatter('%(name)s:%(lineno)d %(levelname)s: %(message)s')\n    console_debug_handler.setFormatter(debug_formatter)\n    console_error_handler.setFormatter(error_formatter)\n    # add ch to logger\n    _logger.addHandler(console_out_handler)\n    _logger.addHandler(console_error_handler)\n    _logger.addHandler(console_debug_handler)\n
                                    "},{"location":"api_reference/trestle.common.log/#trestle.common.log.set_log_level_from_args","title":"set_log_level_from_args(args)","text":"

                                    Vanity function to automatically set log levels based on verbosity flags.

                                    Source code in trestle/common/log.py
                                    def set_log_level_from_args(args: argparse.Namespace) -> None:\n\"\"\"Vanity function to automatically set log levels based on verbosity flags.\"\"\"\n    if args.verbose > 1:\n        # these msgs only output by trace calls\n        set_global_logging_levels(_get_trace_level())\n    elif args.verbose == 1:\n        set_global_logging_levels(logging.DEBUG)\n    else:\n        set_global_logging_levels(logging.INFO)\n        sys.excepthook = _exception_handler\n
                                    "},{"location":"api_reference/trestle.common.model_utils/","title":"model_utils","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils","title":"trestle.common.model_utils","text":"

                                    Common utilities for the OSCAL models and directories.

                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils","title":" ModelUtils ","text":"

                                    Utilities for the OSCAL models input and output.

                                    Source code in trestle/common/model_utils.py
                                    class ModelUtils:\n\"\"\"Utilities for the OSCAL models input and output.\"\"\"\n\n    @staticmethod\n    def load_distributed(\n        abs_path: Path,\n        abs_trestle_root: Path,\n        collection_type: Optional[Type[Any]] = None\n    ) -> Tuple[Type[OscalBaseModel],\n               str,\n               Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]]]:\n\"\"\"\n        Given path to a model, load the model.\n\n        If the model is decomposed/split/distributed,the decomposed models are loaded recursively.\n\n        Args:\n            abs_path: The path to the file/directory to be loaded.\n            abs_trestle_root: The trestle workspace root directory.\n            collection_type: The type of collection model, if it is a collection model.\n                typing.List is the only collection type handled or expected.\n                Defaults to None.\n\n        Returns:\n            Return a tuple of Model Type (e.g. class 'trestle.oscal.catalog.Catalog'),\n            Model Alias (e.g. 'catalog.metadata') and Instance of the Model.\n            If the model is decomposed/split/distributed, the instance of the model contains\n            the decomposed models loaded recursively.\n\n        Note:\n            This does not validate the model.  You must either validate the model separately or use the load_validate\n            utilities.\n        \"\"\"\n        # if trying to load file that does not exist, load path instead\n        if not abs_path.exists():\n            abs_path = abs_path.with_name(abs_path.stem)\n\n        if not abs_path.exists():\n            raise TrestleNotFoundError(f'File {abs_path} not found for load.')\n\n        if collection_type:\n            # If the path contains a list type model\n            if collection_type is list:\n                return ModelUtils._load_list(abs_path, abs_trestle_root)\n            # the only other collection type in OSCAL is dict, and it only applies to include_all,\n            # which is too granular ever to be loaded by this routine\n            else:\n                raise TrestleError(f'Collection type {collection_type} not recognized for distributed load.')\n\n        # Get current model\n        primary_model_type, primary_model_alias = ModelUtils.get_stripped_model_type(abs_path, abs_trestle_root)\n        primary_model_instance: Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]] = None\n\n        # is this an attempt to load an actual json or yaml file?\n        content_type = FileContentType.path_to_content_type(abs_path)\n        # if file is sought but it doesn't exist, ignore and load as decomposed model\n        if FileContentType.is_readable_file(content_type) and abs_path.exists():\n            primary_model_instance = primary_model_type.oscal_read(abs_path)\n        # Is model decomposed?\n        decomposed_dir = abs_path.with_name(abs_path.stem)\n\n        if decomposed_dir.exists():\n            aliases_not_to_be_stripped = []\n            instances_to_be_merged: List[OscalBaseModel] = []\n\n            for local_path in sorted(trestle.common.file_utils.iterdir_without_hidden_files(decomposed_dir)):\n                if local_path.is_file():\n                    model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path, abs_trestle_root)\n                    aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                    instances_to_be_merged.append(model_instance)\n\n                elif local_path.is_dir():\n                    model_type, model_alias = ModelUtils.get_stripped_model_type(local_path, abs_trestle_root)\n                    # Only load the directory if it is a collection model. Otherwise do nothing - it gets loaded when\n                    # iterating over the model file\n\n                    # If a model is just a container for a list e.g.\n                    # class Foo(OscalBaseModel):  noqa: E800\n                    #      __root__: List[Bar]    noqa: E800\n                    # You need to test whether first a root key exists\n                    # then whether the outer_type of root is a collection.\n                    # Alternative is to do a try except to avoid the error for an unknown key.\n\n                    if model_type.is_collection_container():\n                        # This directory is a decomposed List or Dict\n                        collection_type = model_type.get_collection_type()\n                        model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path,\n                                                                                              abs_trestle_root,\n                                                                                              collection_type)\n                        aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                        instances_to_be_merged.append(model_instance)\n            primary_model_dict = {}\n            if primary_model_instance is not None:\n                primary_model_dict = primary_model_instance.__dict__\n\n            merged_model_type, merged_model_alias = ModelUtils.get_stripped_model_type(abs_path,\n                                                                                       abs_trestle_root,\n                                                                                       aliases_not_to_be_stripped)\n\n            # The following use of top_level is to allow loading of a top level model by name only, e.g. MyCatalog\n            # There may be a better overall way to approach this.\n            top_level = len(merged_model_alias.split('.')) == 1\n\n            for i in range(len(aliases_not_to_be_stripped)):\n                alias = aliases_not_to_be_stripped[i]\n                instance = instances_to_be_merged[i]\n                if hasattr(instance, '__dict__') and '__root__' in instance.__dict__ and isinstance(instance,\n                                                                                                    OscalBaseModel):\n                    instance = instance.__dict__['__root__']\n                if top_level and not primary_model_dict:\n                    primary_model_dict = instance.__dict__\n                else:\n                    primary_model_dict[alias] = instance\n\n            merged_model_instance = merged_model_type(**primary_model_dict)\n            return merged_model_type, merged_model_alias, merged_model_instance\n        return primary_model_type, primary_model_alias, primary_model_instance\n\n    @staticmethod\n    def load_model_for_class(\n        trestle_root: pathlib.Path,\n        model_name: str,\n        model_class: TG,\n        file_content_type: Optional[FileContentType] = None\n    ) -> Tuple[TG, pathlib.Path]:\n\"\"\"Load a model by name and model class and infer file content type if not specified.\n\n        If you need to load an existing model but its content type may not be known, use this method.\n        But the file content type should be specified if it is somehow known.\n\n        Note:  This does not validate the model.  If you want to validate the model use the load_validate utilities.\n        \"\"\"\n        root_model_path = ModelUtils._root_path_for_top_level_model(\n            trestle_root, model_name, model_class\n        )  # type: ignore\n        if file_content_type is None:\n            file_content_type = FileContentType.path_to_content_type(root_model_path)\n        if not FileContentType.is_readable_file(file_content_type):\n            raise TrestleError(f'Unable to load model {model_name} without specifying json or yaml.')\n        full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n        _, _, model = ModelUtils.load_distributed(full_model_path, trestle_root)\n        return model, full_model_path  # type: ignore\n\n    @staticmethod\n    def load_model_for_type(trestle_root: pathlib.Path, model_type: str,\n                            model_name: str) -> Tuple[TopLevelOscalModel, pathlib.Path]:\n\"\"\"Load model for the given type and name.\"\"\"\n        dir_name = ModelUtils.model_type_to_model_dir(model_type)\n        model_path = trestle_root / dir_name / model_name\n\n        if not model_path.exists():\n            raise TrestleError(f'No model is found at path: {model_path}.')\n\n        _, _, oscal_object = ModelUtils.load_distributed(model_path, trestle_root)\n\n        return oscal_object, model_path  # type: ignore\n\n    @staticmethod\n    def save_top_level_model(\n        model: TopLevelOscalModel, trestle_root: pathlib.Path, model_name: str, file_content_type: FileContentType\n    ) -> None:\n\"\"\"Save a model by name and infer model type by inspection.\n\n        You don't need to specify the model type (catalog, profile, etc.) but you must specify the file content type.\n        If the model directory does not exist, it is created.\n        \"\"\"\n        root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model)\n        full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n        if not full_model_path.parent.exists():\n            full_model_path.parent.mkdir(parents=True, exist_ok=True)\n        model.oscal_write(full_model_path)\n\n    @staticmethod\n    def get_relative_model_type(relative_path: pathlib.Path) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n        Given the relative path of a file with respect to 'trestle_root' return the oscal model type.\n\n        Args:\n            relative_path: Relative path of the model with respect to the root directory of the trestle workspace.\n        Returns:\n            Type of Oscal Model for the provided model\n            Alias of that oscal model.\n        \"\"\"\n        if len(relative_path.parts) < 2:\n            raise TrestleError(\n                'Insufficient path length to be a valid relative path w.r.t trestle workspace root directory.'\n            )\n        model_dir = relative_path.parts[0]\n        model_relative_path = pathlib.Path(*relative_path.parts[2:])  # catalogs, profiles, etc\n\n        if model_dir in const.MODEL_DIR_LIST:\n            module_name = const.MODEL_DIR_TO_MODEL_MODULE[model_dir]\n        else:\n            raise TrestleError(f'No valid trestle model type directory (e.g. catalogs) found for {model_dir}.')\n\n        model_type, model_alias = ModelUtils.get_root_model(module_name)\n        full_alias = model_alias\n\n        for index, part in enumerate(model_relative_path.parts):\n            alias = ModelUtils._extract_alias(part)\n            if index > 0 or model_alias != alias:\n                model_alias = alias\n                full_alias = f'{full_alias}.{model_alias}'\n                if utils.is_collection_field_type(model_type):\n                    model_type = utils.get_inner_type(model_type)\n                else:\n                    model_type = model_type.alias_to_field_map()[alias].outer_type_\n\n        return model_type, full_alias\n\n    @staticmethod\n    def get_stripped_model_type(\n        absolute_path: pathlib.Path,\n        absolute_trestle_root: pathlib.Path,\n        aliases_not_to_be_stripped: List[str] = None\n    ) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n        Get the stripped contextual model class and alias based on the contextual path.\n\n        This function relies on the directory structure of the trestle model being edited to determine, based on the\n        existing files and folder, which fields should be stripped from the model type represented by the\n        path passed in as a parameter.\n        \"\"\"\n        if aliases_not_to_be_stripped is None:\n            aliases_not_to_be_stripped = []\n        singular_model_type, model_alias = ModelUtils.get_relative_model_type(\n            absolute_path.relative_to(absolute_trestle_root))\n        logger.debug(f'singular model type {singular_model_type} model alias {model_alias}')\n\n        # Stripped models do not apply to collection types such as List[] and Dict{}\n        # if model type is a list or dict, generate a new wrapping model for it\n        if utils.is_collection_field_type(singular_model_type):\n            malias = model_alias.split('.')[-1]\n            class_name = alias_to_classname(malias, AliasMode.JSON)\n            logger.debug(f'collection field type class name {class_name} and alias {malias}')\n            model_type = create_model(class_name, __base__=OscalBaseModel, __root__=(singular_model_type, ...))\n            logger.debug(f'model_type created: {model_type}')\n            return model_type, model_alias\n\n        malias = model_alias.split('.')[-1]\n        logger.debug(f'not collection field type, malias: {malias}')\n        if absolute_path.is_dir() and malias != ModelUtils._extract_alias(absolute_path.name):\n            split_subdir = absolute_path / malias\n        else:\n            split_subdir = absolute_path.parent / absolute_path.with_suffix('').name\n\n        aliases_to_be_stripped = set()\n        if split_subdir.exists():\n            for f in iterdir_without_hidden_files(split_subdir):\n                alias = ModelUtils._extract_alias(f.name)\n                if alias not in aliases_not_to_be_stripped:\n                    aliases_to_be_stripped.add(alias)\n\n        logger.debug(f'aliases to be stripped: {aliases_to_be_stripped}')\n        if len(aliases_to_be_stripped) > 0:\n            model_type = singular_model_type.create_stripped_model_type(\n                stripped_fields_aliases=list(aliases_to_be_stripped)\n            )\n            logger.debug(f'model_type: {model_type}')\n            return model_type, model_alias\n        return singular_model_type, model_alias\n\n    @staticmethod\n    def model_type_to_model_dir(model_type: str) -> str:\n\"\"\"Get plural model directory from model type.\"\"\"\n        if model_type not in const.MODEL_TYPE_LIST:\n            raise err.TrestleError(f'Not a valid model type: {model_type}.')\n        return const.MODEL_TYPE_TO_MODEL_DIR[model_type]\n\n    @staticmethod\n    def get_models_of_type(model_type: str, root: pathlib.Path) -> List[str]:\n\"\"\"Get list of model names for requested type in trestle directory.\"\"\"\n        if model_type not in const.MODEL_TYPE_LIST:\n            raise err.TrestleError(f'Model type {model_type} is not supported')\n        # search relative to project root\n        trestle_root = extract_trestle_project_root(root)\n        if not trestle_root:\n            logger.error(f'Given directory {root} is not within a trestle project.')\n            raise err.TrestleError('Given directory is not within a trestle project.')\n\n        # contruct path to the model file name\n        model_dir_name = ModelUtils.model_type_to_model_dir(model_type)\n        root_model_dir = trestle_root / model_dir_name\n        model_list = []\n        for f in root_model_dir.glob('*/'):\n            # only look for proper json and yaml files\n            if not ModelUtils._should_ignore(f.stem):\n                if not f.is_dir():\n                    logger.warning(\n                        f'Ignoring validation of misplaced file {f.name} '\n                        + f'found in the model directory, {model_dir_name}.'\n                    )\n                else:\n                    model_list.append(f.stem)\n        return model_list\n\n    @staticmethod\n    def get_all_models(root: pathlib.Path) -> List[Tuple[str, str]]:\n\"\"\"Get list of all models in trestle directory as tuples (model_type, model_name).\"\"\"\n        full_list = []\n        for model_type in const.MODEL_TYPE_LIST:\n            models = ModelUtils.get_models_of_type(model_type, root)\n            for m in models:\n                full_list.append((model_type, m))\n        return full_list\n\n    @staticmethod\n    def get_model_path_for_name_and_class(\n        trestle_root: pathlib.Path,\n        model_name: str,\n        model_class: Type[TopLevelOscalModel],\n        file_content_type: Optional[FileContentType] = None\n    ) -> Optional[pathlib.Path]:\n\"\"\"\n        Find the full path of a model given its name, model type and file content type.\n\n        If file_content_type is given it will not inspect the file system or confirm the needed path and file exists.\n        \"\"\"\n        if file_content_type is None:\n            root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n            file_content_type = FileContentType.path_to_content_type(root_model_path)\n            if not FileContentType.is_readable_file(file_content_type):\n                return None\n\n            return root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n\n        root_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n        return root_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n\n    @staticmethod\n    def get_singular_alias(alias_path: str, relative_path: Optional[pathlib.Path] = None) -> str:\n\"\"\"\n        Get the alias in the singular form from a jsonpath.\n\n        If contextual_mode is True and contextual_path is None, it assumes alias_path\n        is relative to the directory the user is running trestle from.\n\n        Args:\n            alias_path: The current alias element path as a string\n            relative_path: Optional relative path (w.r.t. trestle_root) to cater for relative element paths.\n        Returns:\n            Alias as a string\n        \"\"\"\n        if len(alias_path.strip()) == 0:\n            raise err.TrestleError(f'Invalid jsonpath {alias_path}')\n\n        singular_alias: str = ''\n\n        full_alias_path = alias_path\n        if relative_path:\n            logger.debug(f'get_singular_alias contextual mode: {str}')\n            _, full_model_alias = ModelUtils.get_relative_model_type(relative_path)\n            first_alias_a = full_model_alias.split('.')[-1]\n            first_alias_b = alias_path.split('.')[0]\n            if first_alias_a == first_alias_b:\n                full_model_alias = '.'.join(full_model_alias.split('.')[:-1])\n            full_alias_path = '.'.join([full_model_alias, alias_path]).strip('.')\n\n        path_parts = full_alias_path.split(const.ALIAS_PATH_SEPARATOR)\n        logger.debug(f'path parts: {path_parts}')\n\n        model_types = []\n\n        root_model_alias = path_parts[0]\n        found = False\n        for module_name in const.MODEL_TYPE_TO_MODEL_MODULE.values():\n            model_type, model_alias = ModelUtils.get_root_model(module_name)\n            if root_model_alias == model_alias:\n                found = True\n                model_types.append(model_type)\n                break\n\n        if not found:\n            raise err.TrestleError(f'{root_model_alias} is an invalid root model alias.')\n\n        if len(path_parts) == 1:\n            return root_model_alias\n\n        model_type = model_types[0]\n        # go through path parts skipping first one\n        for i in range(1, len(path_parts)):\n            if utils.is_collection_field_type(model_type):\n                # if it is a collection type and last part is * then break\n                if i == len(path_parts) - 1 and path_parts[i] == '*':\n                    break\n                # otherwise get the inner type of items in the collection\n                model_type = utils.get_inner_type(model_type)\n                # and bump i\n                i = i + 1\n            else:\n                path_part = path_parts[i]\n                field_map = model_type.alias_to_field_map()\n                if path_part not in field_map:\n                    continue\n                field = field_map[path_part]\n                model_type = field.outer_type_\n            model_types.append(model_type)\n\n        last_alias = path_parts[-1]\n        if last_alias == '*':\n            last_alias = path_parts[-2]\n\n        # generic model and not list, so return itself fixme doc\n        if not utils.is_collection_field_type(model_type):\n            return last_alias\n\n        parent_model_type = model_types[-2]\n        try:\n            field_map = parent_model_type.alias_to_field_map()\n            field = field_map[last_alias]\n            outer_type = field.outer_type_\n            inner_type = utils.get_inner_type(outer_type)\n            inner_type_name = inner_type.__name__\n            singular_alias = str_utils.classname_to_alias(inner_type_name, AliasMode.JSON)\n        except Exception as e:\n            raise err.TrestleError(f'Error in json path {alias_path}: {e}')\n\n        return singular_alias\n\n    @staticmethod\n    def get_root_model(module_name: str) -> Tuple[Type[Any], str]:\n\"\"\"Get the root model class and alias based on the module.\"\"\"\n        try:\n            module = importlib.import_module(module_name)\n        except ModuleNotFoundError as e:\n            raise err.TrestleError(str(e))\n\n        if hasattr(module, 'Model'):\n            model_metadata = next(iter(module.Model.__fields__.values()))\n            return model_metadata.type_, model_metadata.alias\n        raise err.TrestleError('Invalid module')\n\n    @staticmethod\n    def _root_path_for_top_level_model(\n        trestle_root: pathlib.Path, model_name: str, model_class: Union[TopLevelOscalModel, Type[TopLevelOscalModel]]\n    ) -> pathlib.Path:\n\"\"\"\n        Find the root path to a model given its name and class - with no suffix.\n\n        This is a private method used only to construct the root filepath based on model name and type.\n        It does not check for existence or content type and it does not create the directory if it does not exist.\n        \"\"\"\n        if not hasattr(model_class, '__module__') or model_class.__module__ not in const.MODEL_MODULE_LIST:\n            raise TrestleError(f'Unable to determine model type for model {model_name} with class {model_class}')\n        model_alias = const.MODEL_MODULE_TO_MODEL_TYPE[model_class.__module__]\n        model_dir = trestle_root / f'{const.MODEL_TYPE_TO_MODEL_DIR[model_alias]}/{model_name}'\n        return model_dir / model_alias\n\n    @staticmethod\n    def _extract_alias(string_dir: str) -> str:\n\"\"\"\n        Extract alias from filename or directory name removing extensions and prefixes related to dict and list.\n\n        As we need to do this for multiple parts of a path operating on strings is easier.\n        \"\"\"\n        alias = string_dir.split('.')[0].split(\n            const.IDX_SEP\n        )[-1]  # get suffix of file or directory name representing list or dict item\n        return alias\n\n    @staticmethod\n    def _should_ignore(name: str) -> bool:\n\"\"\"Check if the file or directory should be ignored or not.\"\"\"\n        return name[0] == '.' or name[0] == '_'\n\n    @staticmethod\n    def _load_list(abs_path: Path, abs_trestle_root: Path) -> Tuple[Type[OscalBaseModel], str, List[OscalBaseModel]]:\n\"\"\"Given path to a directory of list(array) models, load the distributed models.\"\"\"\n        aliases_not_to_be_stripped = []\n        instances_to_be_merged: List[OscalBaseModel] = []\n        collection_model_type, collection_model_alias = ModelUtils.get_stripped_model_type(abs_path, abs_trestle_root)\n        for path in sorted(trestle.common.file_utils.iterdir_without_hidden_files(abs_path)):\n\n            # ASSUMPTION HERE: if it is a directory, there's a file that can not be decomposed further.\n            if path.is_dir():\n                continue\n            _, model_alias, model_instance = ModelUtils.load_distributed(path, abs_trestle_root)\n\n            instances_to_be_merged.append(model_instance)\n            aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n\n        return collection_model_type, collection_model_alias, instances_to_be_merged\n\n    @staticmethod\n    def _parameter_to_dict_recurse(obj: Union[OscalBaseModel, str], partial: bool) -> Union[str, Dict[str, Any]]:\n\"\"\"\n        Convert obj to dict containing only string values with recursion.\n\n        Args:\n            obj: The parameter or its consituent parts in recursive calls\n            partial: Whether to convert the entire param or just the parts needed for markdown header\n\n        Returns:\n            The converted parameter as dictionary\n        \"\"\"\n        main_fields = ['id', 'label', 'values', 'select', 'choice', 'how_many', 'guidelines', 'prose']\n        if isinstance(obj, common.Remarks):\n            return obj.__root__\n        if isinstance(obj, common.HowMany):\n            return obj.value\n        # it is either a string already or we cast it to string\n        if not hasattr(obj, const.FIELDS_SET):\n            return str(obj)\n        # it is an oscal object and we need to recurse within its attributes\n        res = {}\n        for field in obj.__fields_set__:\n            if partial and field not in main_fields:\n                continue\n            attr = getattr(obj, field)\n            if not attr:\n                continue\n            if isinstance(attr, list):\n                new_list = []\n                for item in attr:\n                    new_list.append(ModelUtils._parameter_to_dict_recurse(item, partial))\n                res[field] = new_list\n            elif isinstance(attr, str):\n                res[field] = attr\n            else:\n                res[field] = ModelUtils._parameter_to_dict_recurse(attr, partial)\n        return res\n\n    @staticmethod\n    def parameter_to_dict(obj: Union[OscalBaseModel, str], partial: bool) -> Union[str, Dict[str, Any]]:\n\"\"\"\n        Convert obj to dict containing only string values, storing only the fields that have values set.\n\n        Args:\n            obj: The parameter or its consituent parts in recursive calls\n            partial: Whether to convert the entire param or just the parts needed for markdown header\n\n        Returns:\n            The converted parameter as dictionary, with values as None if not present\n        \"\"\"\n        res = ModelUtils._parameter_to_dict_recurse(obj, partial)\n        if 'values' not in res:\n            res['values'] = None  # type: ignore\n        return res\n\n    @staticmethod\n    def _string_to_howmany(count_str: str) -> Optional[str]:\n        clean_str = count_str.lower().strip().replace('-', ' ').replace('_', ' ')\n        if clean_str == const.ONE:\n            return common.HowMany.one  # type: ignore\n        if clean_str == const.ONE_OR_MORE_SPACED:\n            return common.HowMany.one_or_more  # type: ignore\n        return None\n\n    @staticmethod\n    def dict_to_parameter(param_dict: Dict[str, Any]) -> common.Parameter:\n\"\"\"\n        Convert dict with only string values to Parameter with handling for HowMany and with validity checks.\n\n        Args:\n            param_dict: Dictionary of pure string values representing Parameter contents\n\n        Returns:\n            A valid OSCAL Parameter\n\n        Notes:\n            This handles both partial and full parameter dictionaries\n            It checks for validity of the values if a select and HowMany is specified\n            There is special handling for values: If it is a single string it is converted to list of one ParameterValue\n            But if it is a list of strings is regarded as a list of values and is converted to a list of ParameterValues\n        \"\"\"\n        values = param_dict.get('values', [])\n        # special handling when only one value present - convert to list of 1\n        if isinstance(values, str):\n            values = [values]\n            param_dict['values'] = values\n        if 'select' in param_dict and 'how_many' in param_dict['select']:\n            count_str = param_dict['select']['how_many']\n            how_many = ModelUtils._string_to_howmany(count_str)\n            if how_many is None:\n                raise TrestleError(f'Unrecognized HowMany value {how_many} in Parameter: should be one-or-more or one.')\n            param_dict['select']['how_many'] = how_many\n            if how_many == const.ONE and len(values) > 1:\n                logger.warning(f'Parameter specifies HowMany=1 but has {len(values)} values given.')\n            choices = param_dict['select'].get('choice', [])\n            if choices and values:\n                for value in values:\n                    if value not in choices:\n                        logger.warning(f\"Parameter {param_dict['id']} has value \\\"{value}\\\" not in choices: {choices}.\")\n        props = param_dict.get('props', [])\n        if const.DISPLAY_NAME in param_dict:\n            display_name = param_dict.pop(const.DISPLAY_NAME)\n            props.append(common.Property(name=const.DISPLAY_NAME, value=display_name, ns=const.TRESTLE_GENERIC_NS))\n        if const.AGGREGATES in param_dict:\n            # removing aggregates as this is prop just informative in markdown\n            param_dict.pop(const.AGGREGATES)\n        param_value_origin = None\n        if const.PARAM_VALUE_ORIGIN in param_dict:\n            param_value_origin = param_dict.pop(const.PARAM_VALUE_ORIGIN)\n            if param_value_origin is not None:\n                props.append(common.Property(name=const.PARAM_VALUE_ORIGIN, value=param_value_origin))\n            else:\n                raise TrestleError(\n                    f'Parameter value origin property for parameter {param_dict[\"id\"]}'\n                    'is None and it should have a value'\n                )\n        if const.ALT_IDENTIFIER in param_dict:\n            # removing alt-identifier as this is prop just informative in markdown\n            param_dict.pop(const.ALT_IDENTIFIER)\n\n        if 'ns' in param_dict:\n            param_dict.pop('ns')\n        param = common.Parameter(**param_dict)\n        param.props = none_if_empty(props)\n        return param\n\n    @staticmethod\n    def last_modified_at_time(timestamp: Optional[datetime] = None) -> datetime:\n\"\"\"Generate a LastModified set to timestamp or now.\"\"\"\n        timestamp = timestamp if timestamp else datetime.now().astimezone()\n        return timestamp\n\n    @staticmethod\n    def update_last_modified(model: TopLevelOscalModel, timestamp: Optional[datetime] = None) -> None:\n\"\"\"Update the LastModified timestamp in top level model to now.\"\"\"\n        timestamp = timestamp if timestamp else datetime.now().astimezone()\n        model.metadata.last_modified = timestamp\n\n    @staticmethod\n    def model_age(model: TopLevelOscalModel) -> int:\n\"\"\"Find time in seconds since LastModified timestamp.\"\"\"\n        # default to one year if no last_modified\n        age_seconds = const.DAY_SECONDS * 365\n        if model.metadata.last_modified:\n            dt = datetime.now().astimezone() - model.metadata.last_modified\n            age_seconds = dt.seconds\n        return age_seconds\n\n    @staticmethod\n    def find_values_by_name(object_of_interest: Any, name_of_interest: str) -> List[Any]:\n\"\"\"Traverse object and return list of values of specified name.\"\"\"\n        loe = []\n        if isinstance(object_of_interest, BaseModel):\n            value = getattr(object_of_interest, name_of_interest, None)\n            if value is not None:\n                loe.append(value)\n            fields = getattr(object_of_interest, const.FIELDS_SET, None)\n            if fields is not None:\n                for field in fields:\n                    loe.extend(\n                        ModelUtils.find_values_by_name(getattr(object_of_interest, field, None), name_of_interest)\n                    )\n        elif type(object_of_interest) is list:\n            for item in object_of_interest:\n                loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n        elif type(object_of_interest) is dict:\n            if name_of_interest in object_of_interest:\n                loe.append(object_of_interest[name_of_interest])\n            for item in object_of_interest.values():\n                loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n        return loe\n\n    @staticmethod\n    def has_no_duplicate_values_by_name(object_of_interest: BaseModel, name_of_interest: str) -> bool:\n\"\"\"Determine if duplicate values of type exist in object.\"\"\"\n        loe = ModelUtils.find_values_by_name(object_of_interest, name_of_interest)\n        set_loe = set(loe)\n        if len(loe) == len(set_loe):\n            return True\n        items: Dict[str, Any] = {}\n        for item in loe:\n            items[item] = items.get(item, 0) + 1\n        # now print items\n        for item, instances in items.items():\n            if instances > 1:\n                logger.warning(f'Duplicate detected of item {item} with {instances} instances.')\n        return False\n\n    @staticmethod\n    def find_uuid_refs(object_of_interest: BaseModel) -> Set[str]:\n\"\"\"Find uuid references made in prose and links.\"\"\"\n        # hrefs have form #foo or #uuid\n        uuid_strs = ModelUtils.find_values_by_name(object_of_interest, 'href')\n\n        # prose has uuid refs in markdown form: [foo](#bar) or [foo](#uuid)\n        prose_list = ModelUtils.find_values_by_name(object_of_interest, 'prose')\n        for prose in prose_list:\n            matches = re.findall(const.MARKDOWN_URL_REGEX, prose)\n            # the [1] is to extract the inner of 3 capture patterns\n            new_uuids = [match[1] for match in matches]\n            uuid_strs.extend(new_uuids)\n\n        # collect the strings that start with # and are potential uuids\n        uuid_strs = [uuid_str for uuid_str in uuid_strs if uuid_str and uuid_str[0] == '#']\n\n        # go through all matches and build set of those that are uuids\n        uuid_set = {uuid_match for uuid_str in uuid_strs for uuid_match in re.findall(const.UUID_REGEX, uuid_str[1:])}\n        return uuid_set\n\n    @staticmethod\n    def _regenerate_uuids_in_place(object_of_interest: Any, uuid_lut: Dict[str, str]) -> Tuple[Any, Dict[str, str]]:\n\"\"\"Update all uuids in model that require updating.\n\n        Go through the model and replace all dicts with key == 'uuid' and replace the value with a new uuid4.\n        Build a lookup table of the updates that were made.\n        This function does not update the corresponding refs to those uuid's.  That is done by update_uuid_refs\n        Note that this function needs to be started off with uuid_lut == {}, i.e. an empty dict.\n        After that it recurses and grows the lut.\n\n        Args:\n            object_of_interest: pydantic.BaseModel, list, dict or str will be updated\n            uuid_lut: dict of the growing lut of old:new uuid's.  First call must be made with value {}\n\n        Returns:\n            The updated object_of_interest with new uuid's (but refs to them are not updated)\n            The final lookup table of old:new uuid's\n\n        \"\"\"\n        uuid_str = 'uuid'\n        # Certain types are known not to need updating and should not change\n        # Resources are identified by uuid, and the corresponding href will have # in front of the uuid string\n        # Neither of these should change\n        # If other similar types are found they should be added to the FixedUuidModel typevar to prevent updating\n        if isinstance(object_of_interest, common.Resource):\n            pass\n        elif isinstance(object_of_interest, BaseModel):\n            # fields has names of all fields in model\n            fields = getattr(object_of_interest, const.FIELDS_SET, None)\n            for field in fields:\n                new_object = None\n                if field == uuid_str:\n                    orig_uuid = getattr(object_of_interest, field)\n                    if orig_uuid:\n                        new_object = str(uuid.uuid4())\n                        uuid_lut[orig_uuid] = new_object\n                else:\n                    new_object, uuid_lut = ModelUtils._regenerate_uuids_in_place(\n                        object_of_interest.__dict__[field],\n                        uuid_lut\n                    )\n                object_of_interest.__dict__[field] = new_object\n        elif type(object_of_interest) is list:\n            new_list = []\n            for item in object_of_interest:\n                new_item, uuid_lut = ModelUtils._regenerate_uuids_in_place(item, uuid_lut)\n                new_list.append(new_item)\n            object_of_interest = new_list\n        elif type(object_of_interest) is dict:\n            new_dict = {}\n            for key, value in object_of_interest.items():\n                if key == uuid_str:\n                    new_val = str(uuid.uuid4())\n                    new_dict[uuid_str] = new_val\n                    uuid_lut[value] = new_val\n                else:\n                    new_value, uuid_lut = ModelUtils._regenerate_uuids_in_place(value, uuid_lut)\n                    new_dict[key] = new_value\n            object_of_interest = new_dict\n        return object_of_interest, uuid_lut\n\n    @staticmethod\n    def _update_new_uuid_refs(object_of_interest: Any, uuid_lut: Dict[str, str]) -> Tuple[Any, int]:\n\"\"\"Update all refs to uuids that were changed.\"\"\"\n        n_refs_updated = 0\n        if isinstance(object_of_interest, BaseModel):\n            fields = getattr(object_of_interest, const.FIELDS_SET, None)\n            for field in fields:\n                new_object, n_new_updates = ModelUtils._update_new_uuid_refs(\n                    object_of_interest.__dict__[field],\n                    uuid_lut\n                )\n                n_refs_updated += n_new_updates\n                object_of_interest.__dict__[field] = new_object\n        elif type(object_of_interest) is list:\n            new_list = []\n            for item in object_of_interest:\n                new_item, n_new_updates = ModelUtils._update_new_uuid_refs(item, uuid_lut)\n                n_refs_updated += n_new_updates\n                new_list.append(new_item)\n            object_of_interest = new_list\n        elif type(object_of_interest) is dict:\n            new_dict = {}\n            for key, value in object_of_interest.items():\n                if isinstance(value, str):\n                    if value in uuid_lut:\n                        new_dict[key] = uuid_lut[value]\n                        n_refs_updated += 1\n                    else:\n                        new_dict[key] = value\n                else:\n                    new_value, n_new_updates = ModelUtils._update_new_uuid_refs(value, uuid_lut)\n                    n_refs_updated += n_new_updates\n                    new_dict[key] = new_value\n            object_of_interest = new_dict\n        elif isinstance(object_of_interest, str):\n            if object_of_interest in uuid_lut:\n                n_refs_updated += 1\n                object_of_interest = uuid_lut[object_of_interest]\n        return object_of_interest, n_refs_updated\n\n    @staticmethod\n    def regenerate_uuids(object_of_interest: Any) -> Tuple[Any, Dict[str, str], int]:\n\"\"\"Regenerate all uuids in object and update corresponding references.\n\n        Find all dicts with key == 'uuid' and replace the value with a new uuid4.\n        Build a corresponding lookup table as you go, of old:new uuid values.\n        Then make a second pass through the object and replace all string values\n        present in the lookup table with the new value.\n\n        Args:\n            object_of_interest: pydantic.BaseModel, list, dict or str will be updated\n\n        Returns:\n            The updated object with new uuid's and refs\n            The final lookup table of old:new uuid's\n            A count of the number of refs that were updated\n        \"\"\"\n        new_object, uuid_lut = ModelUtils._regenerate_uuids_in_place(object_of_interest, {})\n        new_object, n_refs_updated = ModelUtils._update_new_uuid_refs(new_object, uuid_lut)\n        return new_object, uuid_lut, n_refs_updated\n\n    @staticmethod\n    def fields_set_non_none(obj: BaseModel) -> Set[str]:\n\"\"\"Find the fields set with Nones and empty items removed.\"\"\"\n        return set(as_filtered_list(list(obj.__fields_set__), lambda f: getattr(obj, f)))\n\n    @staticmethod\n    def _objects_differ(\n        obj_a: Any, obj_b: Any, ignore_type_list: List[Any], ignore_name_list: List[str], ignore_all_uuid: bool\n    ) -> bool:\n\"\"\"\n        Compare two objects with option to ignore given types.\n\n        This does not check for tuples or other structures that won't be found in JSON.\n        \"\"\"\n        obj_a_type = type(obj_a)\n        obj_b_type = type(obj_b)\n        if bool(obj_a) != bool(obj_b) or obj_a_type != obj_b_type:\n            return True\n        if not bool(obj_a):\n            return False\n        if obj_a_type in ignore_type_list:\n            return False\n        if obj_a_type is str:\n            return obj_a != obj_b\n        elif isinstance(obj_a, BaseModel):\n            fields_a = ModelUtils.fields_set_non_none(obj_a)\n            fields_b = ModelUtils.fields_set_non_none(obj_b)\n            if fields_a != fields_b:\n                return True\n            for field in list_utils.as_filtered_list(fields_a, lambda f: f not in ignore_name_list):  # type: ignore\n                if ignore_all_uuid and 'uuid' in field:\n                    continue\n                if ModelUtils._objects_differ(getattr(obj_a, field),\n                                              getattr(obj_b, field),\n                                              ignore_type_list,\n                                              ignore_name_list,\n                                              ignore_all_uuid):\n                    return True\n        elif obj_a_type is list:\n            if len(obj_a) != len(obj_b):\n                return True\n            for item_a, item_b in zip(obj_a, obj_b):\n                if ModelUtils._objects_differ(item_a, item_b, ignore_type_list, ignore_name_list, ignore_all_uuid):\n                    return True\n        elif obj_a_type is dict:\n            if obj_a.keys() != obj_b.keys():\n                return True\n            for key, val in obj_a.items():\n                if ignore_all_uuid and 'uuid' in key:\n                    continue\n                if key not in ignore_name_list and ModelUtils._objects_differ(\n                        val, obj_b[key], ignore_type_list, ignore_name_list, ignore_all_uuid):\n                    return True\n        elif obj_a != obj_b:\n            return True\n        return False\n\n    @staticmethod\n    def models_are_equivalent(\n        model_a: Optional[TopLevelOscalModel],\n        model_b: Optional[TopLevelOscalModel],\n        ignore_all_uuid: bool = False\n    ) -> bool:\n\"\"\"\n        Test if models are equivalent except for last modified and possibly uuid.\n\n        If a model has had uuids regenerated, then all uuids *and references to them* are updated.  This means that\n        special handling is required if a model has had uuids regenerated - when checking equivalence.\n        \"\"\"\n        uuid_type_list = [\n            common.LastModified,\n            common.LocationUuid,\n            common.PartyUuid,\n            common.RelatedRisk,\n            common.Source,\n            assessment_plan.RelatedObservation,\n            assessment_results.RelatedObservation,\n            poam.RelatedObservation,\n            poam.RelatedObservation1\n        ]\n        type_list = uuid_type_list if ignore_all_uuid else [common.LastModified]\n        return not ModelUtils._objects_differ(model_a, model_b, type_list, ['last_modified'], ignore_all_uuid)\n\n    @staticmethod\n    def get_title_from_model_uri(trestle_root: pathlib.Path, uri: str) -> str:\n\"\"\"Get title from model at uri.\"\"\"\n        try:\n            fetcher = cache.FetcherFactory.get_fetcher(trestle_root, uri)\n            model, _ = fetcher.get_oscal()\n            return model.metadata.title\n        except TrestleError as e:\n            logger.warning(f'Error finding title for model at uri {uri}: {e}')\n            raise\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.dict_to_parameter","title":"dict_to_parameter(param_dict) staticmethod","text":"

                                    Convert dict with only string values to Parameter with handling for HowMany and with validity checks.

                                    Parameters:

                                    Name Type Description Default param_dict Dict[str, Any]

                                    Dictionary of pure string values representing Parameter contents

                                    required

                                    Returns:

                                    Type Description Parameter

                                    A valid OSCAL Parameter

                                    Notes

                                    This handles both partial and full parameter dictionaries It checks for validity of the values if a select and HowMany is specified There is special handling for values: If it is a single string it is converted to list of one ParameterValue But if it is a list of strings is regarded as a list of values and is converted to a list of ParameterValues

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef dict_to_parameter(param_dict: Dict[str, Any]) -> common.Parameter:\n\"\"\"\n    Convert dict with only string values to Parameter with handling for HowMany and with validity checks.\n\n    Args:\n        param_dict: Dictionary of pure string values representing Parameter contents\n\n    Returns:\n        A valid OSCAL Parameter\n\n    Notes:\n        This handles both partial and full parameter dictionaries\n        It checks for validity of the values if a select and HowMany is specified\n        There is special handling for values: If it is a single string it is converted to list of one ParameterValue\n        But if it is a list of strings is regarded as a list of values and is converted to a list of ParameterValues\n    \"\"\"\n    values = param_dict.get('values', [])\n    # special handling when only one value present - convert to list of 1\n    if isinstance(values, str):\n        values = [values]\n        param_dict['values'] = values\n    if 'select' in param_dict and 'how_many' in param_dict['select']:\n        count_str = param_dict['select']['how_many']\n        how_many = ModelUtils._string_to_howmany(count_str)\n        if how_many is None:\n            raise TrestleError(f'Unrecognized HowMany value {how_many} in Parameter: should be one-or-more or one.')\n        param_dict['select']['how_many'] = how_many\n        if how_many == const.ONE and len(values) > 1:\n            logger.warning(f'Parameter specifies HowMany=1 but has {len(values)} values given.')\n        choices = param_dict['select'].get('choice', [])\n        if choices and values:\n            for value in values:\n                if value not in choices:\n                    logger.warning(f\"Parameter {param_dict['id']} has value \\\"{value}\\\" not in choices: {choices}.\")\n    props = param_dict.get('props', [])\n    if const.DISPLAY_NAME in param_dict:\n        display_name = param_dict.pop(const.DISPLAY_NAME)\n        props.append(common.Property(name=const.DISPLAY_NAME, value=display_name, ns=const.TRESTLE_GENERIC_NS))\n    if const.AGGREGATES in param_dict:\n        # removing aggregates as this is prop just informative in markdown\n        param_dict.pop(const.AGGREGATES)\n    param_value_origin = None\n    if const.PARAM_VALUE_ORIGIN in param_dict:\n        param_value_origin = param_dict.pop(const.PARAM_VALUE_ORIGIN)\n        if param_value_origin is not None:\n            props.append(common.Property(name=const.PARAM_VALUE_ORIGIN, value=param_value_origin))\n        else:\n            raise TrestleError(\n                f'Parameter value origin property for parameter {param_dict[\"id\"]}'\n                'is None and it should have a value'\n            )\n    if const.ALT_IDENTIFIER in param_dict:\n        # removing alt-identifier as this is prop just informative in markdown\n        param_dict.pop(const.ALT_IDENTIFIER)\n\n    if 'ns' in param_dict:\n        param_dict.pop('ns')\n    param = common.Parameter(**param_dict)\n    param.props = none_if_empty(props)\n    return param\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.fields_set_non_none","title":"fields_set_non_none(obj) staticmethod","text":"

                                    Find the fields set with Nones and empty items removed.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef fields_set_non_none(obj: BaseModel) -> Set[str]:\n\"\"\"Find the fields set with Nones and empty items removed.\"\"\"\n    return set(as_filtered_list(list(obj.__fields_set__), lambda f: getattr(obj, f)))\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.find_uuid_refs","title":"find_uuid_refs(object_of_interest) staticmethod","text":"

                                    Find uuid references made in prose and links.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef find_uuid_refs(object_of_interest: BaseModel) -> Set[str]:\n\"\"\"Find uuid references made in prose and links.\"\"\"\n    # hrefs have form #foo or #uuid\n    uuid_strs = ModelUtils.find_values_by_name(object_of_interest, 'href')\n\n    # prose has uuid refs in markdown form: [foo](#bar) or [foo](#uuid)\n    prose_list = ModelUtils.find_values_by_name(object_of_interest, 'prose')\n    for prose in prose_list:\n        matches = re.findall(const.MARKDOWN_URL_REGEX, prose)\n        # the [1] is to extract the inner of 3 capture patterns\n        new_uuids = [match[1] for match in matches]\n        uuid_strs.extend(new_uuids)\n\n    # collect the strings that start with # and are potential uuids\n    uuid_strs = [uuid_str for uuid_str in uuid_strs if uuid_str and uuid_str[0] == '#']\n\n    # go through all matches and build set of those that are uuids\n    uuid_set = {uuid_match for uuid_str in uuid_strs for uuid_match in re.findall(const.UUID_REGEX, uuid_str[1:])}\n    return uuid_set\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.find_values_by_name","title":"find_values_by_name(object_of_interest, name_of_interest) staticmethod","text":"

                                    Traverse object and return list of values of specified name.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef find_values_by_name(object_of_interest: Any, name_of_interest: str) -> List[Any]:\n\"\"\"Traverse object and return list of values of specified name.\"\"\"\n    loe = []\n    if isinstance(object_of_interest, BaseModel):\n        value = getattr(object_of_interest, name_of_interest, None)\n        if value is not None:\n            loe.append(value)\n        fields = getattr(object_of_interest, const.FIELDS_SET, None)\n        if fields is not None:\n            for field in fields:\n                loe.extend(\n                    ModelUtils.find_values_by_name(getattr(object_of_interest, field, None), name_of_interest)\n                )\n    elif type(object_of_interest) is list:\n        for item in object_of_interest:\n            loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n    elif type(object_of_interest) is dict:\n        if name_of_interest in object_of_interest:\n            loe.append(object_of_interest[name_of_interest])\n        for item in object_of_interest.values():\n            loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n    return loe\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_all_models","title":"get_all_models(root) staticmethod","text":"

                                    Get list of all models in trestle directory as tuples (model_type, model_name).

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_all_models(root: pathlib.Path) -> List[Tuple[str, str]]:\n\"\"\"Get list of all models in trestle directory as tuples (model_type, model_name).\"\"\"\n    full_list = []\n    for model_type in const.MODEL_TYPE_LIST:\n        models = ModelUtils.get_models_of_type(model_type, root)\n        for m in models:\n            full_list.append((model_type, m))\n    return full_list\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_model_path_for_name_and_class","title":"get_model_path_for_name_and_class(trestle_root, model_name, model_class, file_content_type=None) staticmethod","text":"

                                    Find the full path of a model given its name, model type and file content type.

                                    If file_content_type is given it will not inspect the file system or confirm the needed path and file exists.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_model_path_for_name_and_class(\n    trestle_root: pathlib.Path,\n    model_name: str,\n    model_class: Type[TopLevelOscalModel],\n    file_content_type: Optional[FileContentType] = None\n) -> Optional[pathlib.Path]:\n\"\"\"\n    Find the full path of a model given its name, model type and file content type.\n\n    If file_content_type is given it will not inspect the file system or confirm the needed path and file exists.\n    \"\"\"\n    if file_content_type is None:\n        root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n        file_content_type = FileContentType.path_to_content_type(root_model_path)\n        if not FileContentType.is_readable_file(file_content_type):\n            return None\n\n        return root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n\n    root_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n    return root_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_models_of_type","title":"get_models_of_type(model_type, root) staticmethod","text":"

                                    Get list of model names for requested type in trestle directory.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_models_of_type(model_type: str, root: pathlib.Path) -> List[str]:\n\"\"\"Get list of model names for requested type in trestle directory.\"\"\"\n    if model_type not in const.MODEL_TYPE_LIST:\n        raise err.TrestleError(f'Model type {model_type} is not supported')\n    # search relative to project root\n    trestle_root = extract_trestle_project_root(root)\n    if not trestle_root:\n        logger.error(f'Given directory {root} is not within a trestle project.')\n        raise err.TrestleError('Given directory is not within a trestle project.')\n\n    # contruct path to the model file name\n    model_dir_name = ModelUtils.model_type_to_model_dir(model_type)\n    root_model_dir = trestle_root / model_dir_name\n    model_list = []\n    for f in root_model_dir.glob('*/'):\n        # only look for proper json and yaml files\n        if not ModelUtils._should_ignore(f.stem):\n            if not f.is_dir():\n                logger.warning(\n                    f'Ignoring validation of misplaced file {f.name} '\n                    + f'found in the model directory, {model_dir_name}.'\n                )\n            else:\n                model_list.append(f.stem)\n    return model_list\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_relative_model_type","title":"get_relative_model_type(relative_path) staticmethod","text":"

                                    Given the relative path of a file with respect to 'trestle_root' return the oscal model type.

                                    Parameters:

                                    Name Type Description Default relative_path Path

                                    Relative path of the model with respect to the root directory of the trestle workspace.

                                    required

                                    Returns:

                                    Type Description Tuple[Type[trestle.core.base_model.OscalBaseModel], str]

                                    Type of Oscal Model for the provided model Alias of that oscal model.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_relative_model_type(relative_path: pathlib.Path) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n    Given the relative path of a file with respect to 'trestle_root' return the oscal model type.\n\n    Args:\n        relative_path: Relative path of the model with respect to the root directory of the trestle workspace.\n    Returns:\n        Type of Oscal Model for the provided model\n        Alias of that oscal model.\n    \"\"\"\n    if len(relative_path.parts) < 2:\n        raise TrestleError(\n            'Insufficient path length to be a valid relative path w.r.t trestle workspace root directory.'\n        )\n    model_dir = relative_path.parts[0]\n    model_relative_path = pathlib.Path(*relative_path.parts[2:])  # catalogs, profiles, etc\n\n    if model_dir in const.MODEL_DIR_LIST:\n        module_name = const.MODEL_DIR_TO_MODEL_MODULE[model_dir]\n    else:\n        raise TrestleError(f'No valid trestle model type directory (e.g. catalogs) found for {model_dir}.')\n\n    model_type, model_alias = ModelUtils.get_root_model(module_name)\n    full_alias = model_alias\n\n    for index, part in enumerate(model_relative_path.parts):\n        alias = ModelUtils._extract_alias(part)\n        if index > 0 or model_alias != alias:\n            model_alias = alias\n            full_alias = f'{full_alias}.{model_alias}'\n            if utils.is_collection_field_type(model_type):\n                model_type = utils.get_inner_type(model_type)\n            else:\n                model_type = model_type.alias_to_field_map()[alias].outer_type_\n\n    return model_type, full_alias\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_root_model","title":"get_root_model(module_name) staticmethod","text":"

                                    Get the root model class and alias based on the module.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_root_model(module_name: str) -> Tuple[Type[Any], str]:\n\"\"\"Get the root model class and alias based on the module.\"\"\"\n    try:\n        module = importlib.import_module(module_name)\n    except ModuleNotFoundError as e:\n        raise err.TrestleError(str(e))\n\n    if hasattr(module, 'Model'):\n        model_metadata = next(iter(module.Model.__fields__.values()))\n        return model_metadata.type_, model_metadata.alias\n    raise err.TrestleError('Invalid module')\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_singular_alias","title":"get_singular_alias(alias_path, relative_path=None) staticmethod","text":"

                                    Get the alias in the singular form from a jsonpath.

                                    If contextual_mode is True and contextual_path is None, it assumes alias_path is relative to the directory the user is running trestle from.

                                    Parameters:

                                    Name Type Description Default alias_path str

                                    The current alias element path as a string

                                    required relative_path Optional[pathlib.Path]

                                    Optional relative path (w.r.t. trestle_root) to cater for relative element paths.

                                    None

                                    Returns:

                                    Type Description str

                                    Alias as a string

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_singular_alias(alias_path: str, relative_path: Optional[pathlib.Path] = None) -> str:\n\"\"\"\n    Get the alias in the singular form from a jsonpath.\n\n    If contextual_mode is True and contextual_path is None, it assumes alias_path\n    is relative to the directory the user is running trestle from.\n\n    Args:\n        alias_path: The current alias element path as a string\n        relative_path: Optional relative path (w.r.t. trestle_root) to cater for relative element paths.\n    Returns:\n        Alias as a string\n    \"\"\"\n    if len(alias_path.strip()) == 0:\n        raise err.TrestleError(f'Invalid jsonpath {alias_path}')\n\n    singular_alias: str = ''\n\n    full_alias_path = alias_path\n    if relative_path:\n        logger.debug(f'get_singular_alias contextual mode: {str}')\n        _, full_model_alias = ModelUtils.get_relative_model_type(relative_path)\n        first_alias_a = full_model_alias.split('.')[-1]\n        first_alias_b = alias_path.split('.')[0]\n        if first_alias_a == first_alias_b:\n            full_model_alias = '.'.join(full_model_alias.split('.')[:-1])\n        full_alias_path = '.'.join([full_model_alias, alias_path]).strip('.')\n\n    path_parts = full_alias_path.split(const.ALIAS_PATH_SEPARATOR)\n    logger.debug(f'path parts: {path_parts}')\n\n    model_types = []\n\n    root_model_alias = path_parts[0]\n    found = False\n    for module_name in const.MODEL_TYPE_TO_MODEL_MODULE.values():\n        model_type, model_alias = ModelUtils.get_root_model(module_name)\n        if root_model_alias == model_alias:\n            found = True\n            model_types.append(model_type)\n            break\n\n    if not found:\n        raise err.TrestleError(f'{root_model_alias} is an invalid root model alias.')\n\n    if len(path_parts) == 1:\n        return root_model_alias\n\n    model_type = model_types[0]\n    # go through path parts skipping first one\n    for i in range(1, len(path_parts)):\n        if utils.is_collection_field_type(model_type):\n            # if it is a collection type and last part is * then break\n            if i == len(path_parts) - 1 and path_parts[i] == '*':\n                break\n            # otherwise get the inner type of items in the collection\n            model_type = utils.get_inner_type(model_type)\n            # and bump i\n            i = i + 1\n        else:\n            path_part = path_parts[i]\n            field_map = model_type.alias_to_field_map()\n            if path_part not in field_map:\n                continue\n            field = field_map[path_part]\n            model_type = field.outer_type_\n        model_types.append(model_type)\n\n    last_alias = path_parts[-1]\n    if last_alias == '*':\n        last_alias = path_parts[-2]\n\n    # generic model and not list, so return itself fixme doc\n    if not utils.is_collection_field_type(model_type):\n        return last_alias\n\n    parent_model_type = model_types[-2]\n    try:\n        field_map = parent_model_type.alias_to_field_map()\n        field = field_map[last_alias]\n        outer_type = field.outer_type_\n        inner_type = utils.get_inner_type(outer_type)\n        inner_type_name = inner_type.__name__\n        singular_alias = str_utils.classname_to_alias(inner_type_name, AliasMode.JSON)\n    except Exception as e:\n        raise err.TrestleError(f'Error in json path {alias_path}: {e}')\n\n    return singular_alias\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_stripped_model_type","title":"get_stripped_model_type(absolute_path, absolute_trestle_root, aliases_not_to_be_stripped=None) staticmethod","text":"

                                    Get the stripped contextual model class and alias based on the contextual path.

                                    This function relies on the directory structure of the trestle model being edited to determine, based on the existing files and folder, which fields should be stripped from the model type represented by the path passed in as a parameter.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_stripped_model_type(\n    absolute_path: pathlib.Path,\n    absolute_trestle_root: pathlib.Path,\n    aliases_not_to_be_stripped: List[str] = None\n) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n    Get the stripped contextual model class and alias based on the contextual path.\n\n    This function relies on the directory structure of the trestle model being edited to determine, based on the\n    existing files and folder, which fields should be stripped from the model type represented by the\n    path passed in as a parameter.\n    \"\"\"\n    if aliases_not_to_be_stripped is None:\n        aliases_not_to_be_stripped = []\n    singular_model_type, model_alias = ModelUtils.get_relative_model_type(\n        absolute_path.relative_to(absolute_trestle_root))\n    logger.debug(f'singular model type {singular_model_type} model alias {model_alias}')\n\n    # Stripped models do not apply to collection types such as List[] and Dict{}\n    # if model type is a list or dict, generate a new wrapping model for it\n    if utils.is_collection_field_type(singular_model_type):\n        malias = model_alias.split('.')[-1]\n        class_name = alias_to_classname(malias, AliasMode.JSON)\n        logger.debug(f'collection field type class name {class_name} and alias {malias}')\n        model_type = create_model(class_name, __base__=OscalBaseModel, __root__=(singular_model_type, ...))\n        logger.debug(f'model_type created: {model_type}')\n        return model_type, model_alias\n\n    malias = model_alias.split('.')[-1]\n    logger.debug(f'not collection field type, malias: {malias}')\n    if absolute_path.is_dir() and malias != ModelUtils._extract_alias(absolute_path.name):\n        split_subdir = absolute_path / malias\n    else:\n        split_subdir = absolute_path.parent / absolute_path.with_suffix('').name\n\n    aliases_to_be_stripped = set()\n    if split_subdir.exists():\n        for f in iterdir_without_hidden_files(split_subdir):\n            alias = ModelUtils._extract_alias(f.name)\n            if alias not in aliases_not_to_be_stripped:\n                aliases_to_be_stripped.add(alias)\n\n    logger.debug(f'aliases to be stripped: {aliases_to_be_stripped}')\n    if len(aliases_to_be_stripped) > 0:\n        model_type = singular_model_type.create_stripped_model_type(\n            stripped_fields_aliases=list(aliases_to_be_stripped)\n        )\n        logger.debug(f'model_type: {model_type}')\n        return model_type, model_alias\n    return singular_model_type, model_alias\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_title_from_model_uri","title":"get_title_from_model_uri(trestle_root, uri) staticmethod","text":"

                                    Get title from model at uri.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef get_title_from_model_uri(trestle_root: pathlib.Path, uri: str) -> str:\n\"\"\"Get title from model at uri.\"\"\"\n    try:\n        fetcher = cache.FetcherFactory.get_fetcher(trestle_root, uri)\n        model, _ = fetcher.get_oscal()\n        return model.metadata.title\n    except TrestleError as e:\n        logger.warning(f'Error finding title for model at uri {uri}: {e}')\n        raise\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.has_no_duplicate_values_by_name","title":"has_no_duplicate_values_by_name(object_of_interest, name_of_interest) staticmethod","text":"

                                    Determine if duplicate values of type exist in object.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef has_no_duplicate_values_by_name(object_of_interest: BaseModel, name_of_interest: str) -> bool:\n\"\"\"Determine if duplicate values of type exist in object.\"\"\"\n    loe = ModelUtils.find_values_by_name(object_of_interest, name_of_interest)\n    set_loe = set(loe)\n    if len(loe) == len(set_loe):\n        return True\n    items: Dict[str, Any] = {}\n    for item in loe:\n        items[item] = items.get(item, 0) + 1\n    # now print items\n    for item, instances in items.items():\n        if instances > 1:\n            logger.warning(f'Duplicate detected of item {item} with {instances} instances.')\n    return False\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.last_modified_at_time","title":"last_modified_at_time(timestamp=None) staticmethod","text":"

                                    Generate a LastModified set to timestamp or now.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef last_modified_at_time(timestamp: Optional[datetime] = None) -> datetime:\n\"\"\"Generate a LastModified set to timestamp or now.\"\"\"\n    timestamp = timestamp if timestamp else datetime.now().astimezone()\n    return timestamp\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.load_distributed","title":"load_distributed(abs_path, abs_trestle_root, collection_type=None) staticmethod","text":"

                                    Given path to a model, load the model.

                                    If the model is decomposed/split/distributed,the decomposed models are loaded recursively.

                                    Parameters:

                                    Name Type Description Default abs_path Path

                                    The path to the file/directory to be loaded.

                                    required abs_trestle_root Path

                                    The trestle workspace root directory.

                                    required collection_type Optional[Type[Any]]

                                    The type of collection model, if it is a collection model. typing.List is the only collection type handled or expected. Defaults to None.

                                    None

                                    Returns:

                                    Type Description Tuple[Type[trestle.core.base_model.OscalBaseModel], str, Union[trestle.core.base_model.OscalBaseModel, List[trestle.core.base_model.OscalBaseModel], Dict[str, trestle.core.base_model.OscalBaseModel]]]

                                    Return a tuple of Model Type (e.g. class 'trestle.oscal.catalog.Catalog'), Model Alias (e.g. 'catalog.metadata') and Instance of the Model. If the model is decomposed/split/distributed, the instance of the model contains the decomposed models loaded recursively.

                                    Note

                                    This does not validate the model. You must either validate the model separately or use the load_validate utilities.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef load_distributed(\n    abs_path: Path,\n    abs_trestle_root: Path,\n    collection_type: Optional[Type[Any]] = None\n) -> Tuple[Type[OscalBaseModel],\n           str,\n           Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]]]:\n\"\"\"\n    Given path to a model, load the model.\n\n    If the model is decomposed/split/distributed,the decomposed models are loaded recursively.\n\n    Args:\n        abs_path: The path to the file/directory to be loaded.\n        abs_trestle_root: The trestle workspace root directory.\n        collection_type: The type of collection model, if it is a collection model.\n            typing.List is the only collection type handled or expected.\n            Defaults to None.\n\n    Returns:\n        Return a tuple of Model Type (e.g. class 'trestle.oscal.catalog.Catalog'),\n        Model Alias (e.g. 'catalog.metadata') and Instance of the Model.\n        If the model is decomposed/split/distributed, the instance of the model contains\n        the decomposed models loaded recursively.\n\n    Note:\n        This does not validate the model.  You must either validate the model separately or use the load_validate\n        utilities.\n    \"\"\"\n    # if trying to load file that does not exist, load path instead\n    if not abs_path.exists():\n        abs_path = abs_path.with_name(abs_path.stem)\n\n    if not abs_path.exists():\n        raise TrestleNotFoundError(f'File {abs_path} not found for load.')\n\n    if collection_type:\n        # If the path contains a list type model\n        if collection_type is list:\n            return ModelUtils._load_list(abs_path, abs_trestle_root)\n        # the only other collection type in OSCAL is dict, and it only applies to include_all,\n        # which is too granular ever to be loaded by this routine\n        else:\n            raise TrestleError(f'Collection type {collection_type} not recognized for distributed load.')\n\n    # Get current model\n    primary_model_type, primary_model_alias = ModelUtils.get_stripped_model_type(abs_path, abs_trestle_root)\n    primary_model_instance: Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]] = None\n\n    # is this an attempt to load an actual json or yaml file?\n    content_type = FileContentType.path_to_content_type(abs_path)\n    # if file is sought but it doesn't exist, ignore and load as decomposed model\n    if FileContentType.is_readable_file(content_type) and abs_path.exists():\n        primary_model_instance = primary_model_type.oscal_read(abs_path)\n    # Is model decomposed?\n    decomposed_dir = abs_path.with_name(abs_path.stem)\n\n    if decomposed_dir.exists():\n        aliases_not_to_be_stripped = []\n        instances_to_be_merged: List[OscalBaseModel] = []\n\n        for local_path in sorted(trestle.common.file_utils.iterdir_without_hidden_files(decomposed_dir)):\n            if local_path.is_file():\n                model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path, abs_trestle_root)\n                aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                instances_to_be_merged.append(model_instance)\n\n            elif local_path.is_dir():\n                model_type, model_alias = ModelUtils.get_stripped_model_type(local_path, abs_trestle_root)\n                # Only load the directory if it is a collection model. Otherwise do nothing - it gets loaded when\n                # iterating over the model file\n\n                # If a model is just a container for a list e.g.\n                # class Foo(OscalBaseModel):  noqa: E800\n                #      __root__: List[Bar]    noqa: E800\n                # You need to test whether first a root key exists\n                # then whether the outer_type of root is a collection.\n                # Alternative is to do a try except to avoid the error for an unknown key.\n\n                if model_type.is_collection_container():\n                    # This directory is a decomposed List or Dict\n                    collection_type = model_type.get_collection_type()\n                    model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path,\n                                                                                          abs_trestle_root,\n                                                                                          collection_type)\n                    aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                    instances_to_be_merged.append(model_instance)\n        primary_model_dict = {}\n        if primary_model_instance is not None:\n            primary_model_dict = primary_model_instance.__dict__\n\n        merged_model_type, merged_model_alias = ModelUtils.get_stripped_model_type(abs_path,\n                                                                                   abs_trestle_root,\n                                                                                   aliases_not_to_be_stripped)\n\n        # The following use of top_level is to allow loading of a top level model by name only, e.g. MyCatalog\n        # There may be a better overall way to approach this.\n        top_level = len(merged_model_alias.split('.')) == 1\n\n        for i in range(len(aliases_not_to_be_stripped)):\n            alias = aliases_not_to_be_stripped[i]\n            instance = instances_to_be_merged[i]\n            if hasattr(instance, '__dict__') and '__root__' in instance.__dict__ and isinstance(instance,\n                                                                                                OscalBaseModel):\n                instance = instance.__dict__['__root__']\n            if top_level and not primary_model_dict:\n                primary_model_dict = instance.__dict__\n            else:\n                primary_model_dict[alias] = instance\n\n        merged_model_instance = merged_model_type(**primary_model_dict)\n        return merged_model_type, merged_model_alias, merged_model_instance\n    return primary_model_type, primary_model_alias, primary_model_instance\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.load_model_for_class","title":"load_model_for_class(trestle_root, model_name, model_class, file_content_type=None) staticmethod","text":"

                                    Load a model by name and model class and infer file content type if not specified.

                                    If you need to load an existing model but its content type may not be known, use this method. But the file content type should be specified if it is somehow known.

                                    Note: This does not validate the model. If you want to validate the model use the load_validate utilities.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef load_model_for_class(\n    trestle_root: pathlib.Path,\n    model_name: str,\n    model_class: TG,\n    file_content_type: Optional[FileContentType] = None\n) -> Tuple[TG, pathlib.Path]:\n\"\"\"Load a model by name and model class and infer file content type if not specified.\n\n    If you need to load an existing model but its content type may not be known, use this method.\n    But the file content type should be specified if it is somehow known.\n\n    Note:  This does not validate the model.  If you want to validate the model use the load_validate utilities.\n    \"\"\"\n    root_model_path = ModelUtils._root_path_for_top_level_model(\n        trestle_root, model_name, model_class\n    )  # type: ignore\n    if file_content_type is None:\n        file_content_type = FileContentType.path_to_content_type(root_model_path)\n    if not FileContentType.is_readable_file(file_content_type):\n        raise TrestleError(f'Unable to load model {model_name} without specifying json or yaml.')\n    full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n    _, _, model = ModelUtils.load_distributed(full_model_path, trestle_root)\n    return model, full_model_path  # type: ignore\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.load_model_for_type","title":"load_model_for_type(trestle_root, model_type, model_name) staticmethod","text":"

                                    Load model for the given type and name.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef load_model_for_type(trestle_root: pathlib.Path, model_type: str,\n                        model_name: str) -> Tuple[TopLevelOscalModel, pathlib.Path]:\n\"\"\"Load model for the given type and name.\"\"\"\n    dir_name = ModelUtils.model_type_to_model_dir(model_type)\n    model_path = trestle_root / dir_name / model_name\n\n    if not model_path.exists():\n        raise TrestleError(f'No model is found at path: {model_path}.')\n\n    _, _, oscal_object = ModelUtils.load_distributed(model_path, trestle_root)\n\n    return oscal_object, model_path  # type: ignore\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.model_age","title":"model_age(model) staticmethod","text":"

                                    Find time in seconds since LastModified timestamp.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef model_age(model: TopLevelOscalModel) -> int:\n\"\"\"Find time in seconds since LastModified timestamp.\"\"\"\n    # default to one year if no last_modified\n    age_seconds = const.DAY_SECONDS * 365\n    if model.metadata.last_modified:\n        dt = datetime.now().astimezone() - model.metadata.last_modified\n        age_seconds = dt.seconds\n    return age_seconds\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.model_type_to_model_dir","title":"model_type_to_model_dir(model_type) staticmethod","text":"

                                    Get plural model directory from model type.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef model_type_to_model_dir(model_type: str) -> str:\n\"\"\"Get plural model directory from model type.\"\"\"\n    if model_type not in const.MODEL_TYPE_LIST:\n        raise err.TrestleError(f'Not a valid model type: {model_type}.')\n    return const.MODEL_TYPE_TO_MODEL_DIR[model_type]\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.models_are_equivalent","title":"models_are_equivalent(model_a, model_b, ignore_all_uuid=False) staticmethod","text":"

                                    Test if models are equivalent except for last modified and possibly uuid.

                                    If a model has had uuids regenerated, then all uuids and references to them are updated. This means that special handling is required if a model has had uuids regenerated - when checking equivalence.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef models_are_equivalent(\n    model_a: Optional[TopLevelOscalModel],\n    model_b: Optional[TopLevelOscalModel],\n    ignore_all_uuid: bool = False\n) -> bool:\n\"\"\"\n    Test if models are equivalent except for last modified and possibly uuid.\n\n    If a model has had uuids regenerated, then all uuids *and references to them* are updated.  This means that\n    special handling is required if a model has had uuids regenerated - when checking equivalence.\n    \"\"\"\n    uuid_type_list = [\n        common.LastModified,\n        common.LocationUuid,\n        common.PartyUuid,\n        common.RelatedRisk,\n        common.Source,\n        assessment_plan.RelatedObservation,\n        assessment_results.RelatedObservation,\n        poam.RelatedObservation,\n        poam.RelatedObservation1\n    ]\n    type_list = uuid_type_list if ignore_all_uuid else [common.LastModified]\n    return not ModelUtils._objects_differ(model_a, model_b, type_list, ['last_modified'], ignore_all_uuid)\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.parameter_to_dict","title":"parameter_to_dict(obj, partial) staticmethod","text":"

                                    Convert obj to dict containing only string values, storing only the fields that have values set.

                                    Parameters:

                                    Name Type Description Default obj Union[trestle.core.base_model.OscalBaseModel, str]

                                    The parameter or its consituent parts in recursive calls

                                    required partial bool

                                    Whether to convert the entire param or just the parts needed for markdown header

                                    required

                                    Returns:

                                    Type Description Union[str, Dict[str, Any]]

                                    The converted parameter as dictionary, with values as None if not present

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef parameter_to_dict(obj: Union[OscalBaseModel, str], partial: bool) -> Union[str, Dict[str, Any]]:\n\"\"\"\n    Convert obj to dict containing only string values, storing only the fields that have values set.\n\n    Args:\n        obj: The parameter or its consituent parts in recursive calls\n        partial: Whether to convert the entire param or just the parts needed for markdown header\n\n    Returns:\n        The converted parameter as dictionary, with values as None if not present\n    \"\"\"\n    res = ModelUtils._parameter_to_dict_recurse(obj, partial)\n    if 'values' not in res:\n        res['values'] = None  # type: ignore\n    return res\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.regenerate_uuids","title":"regenerate_uuids(object_of_interest) staticmethod","text":"

                                    Regenerate all uuids in object and update corresponding references.

                                    Find all dicts with key == 'uuid' and replace the value with a new uuid4. Build a corresponding lookup table as you go, of old:new uuid values. Then make a second pass through the object and replace all string values present in the lookup table with the new value.

                                    Parameters:

                                    Name Type Description Default object_of_interest Any

                                    pydantic.BaseModel, list, dict or str will be updated

                                    required

                                    Returns:

                                    Type Description The updated object with new uuid's and refs The final lookup table of old

                                    new uuid's A count of the number of refs that were updated

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef regenerate_uuids(object_of_interest: Any) -> Tuple[Any, Dict[str, str], int]:\n\"\"\"Regenerate all uuids in object and update corresponding references.\n\n    Find all dicts with key == 'uuid' and replace the value with a new uuid4.\n    Build a corresponding lookup table as you go, of old:new uuid values.\n    Then make a second pass through the object and replace all string values\n    present in the lookup table with the new value.\n\n    Args:\n        object_of_interest: pydantic.BaseModel, list, dict or str will be updated\n\n    Returns:\n        The updated object with new uuid's and refs\n        The final lookup table of old:new uuid's\n        A count of the number of refs that were updated\n    \"\"\"\n    new_object, uuid_lut = ModelUtils._regenerate_uuids_in_place(object_of_interest, {})\n    new_object, n_refs_updated = ModelUtils._update_new_uuid_refs(new_object, uuid_lut)\n    return new_object, uuid_lut, n_refs_updated\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.save_top_level_model","title":"save_top_level_model(model, trestle_root, model_name, file_content_type) staticmethod","text":"

                                    Save a model by name and infer model type by inspection.

                                    You don't need to specify the model type (catalog, profile, etc.) but you must specify the file content type. If the model directory does not exist, it is created.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef save_top_level_model(\n    model: TopLevelOscalModel, trestle_root: pathlib.Path, model_name: str, file_content_type: FileContentType\n) -> None:\n\"\"\"Save a model by name and infer model type by inspection.\n\n    You don't need to specify the model type (catalog, profile, etc.) but you must specify the file content type.\n    If the model directory does not exist, it is created.\n    \"\"\"\n    root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model)\n    full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n    if not full_model_path.parent.exists():\n        full_model_path.parent.mkdir(parents=True, exist_ok=True)\n    model.oscal_write(full_model_path)\n
                                    "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.update_last_modified","title":"update_last_modified(model, timestamp=None) staticmethod","text":"

                                    Update the LastModified timestamp in top level model to now.

                                    Source code in trestle/common/model_utils.py
                                    @staticmethod\ndef update_last_modified(model: TopLevelOscalModel, timestamp: Optional[datetime] = None) -> None:\n\"\"\"Update the LastModified timestamp in top level model to now.\"\"\"\n    timestamp = timestamp if timestamp else datetime.now().astimezone()\n    model.metadata.last_modified = timestamp\n
                                    "},{"location":"api_reference/trestle.common.str_utils/","title":"str_utils","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils","title":"trestle.common.str_utils","text":"

                                    Trestle String Utils.

                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.AliasMode","title":" AliasMode (Enum) ","text":"

                                    Allowed formats for classname alias.

                                    Currently there are only two. If others are added, check they get handled properly in the code.

                                    Source code in trestle/common/str_utils.py
                                    class AliasMode(enum.Enum):\n\"\"\"\n    Allowed formats for classname alias.\n\n    Currently there are only two.  If others are added, check they get handled properly in the code.\n    \"\"\"\n\n    JSON = 1\n    FIELD = 2\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.AliasMode.FIELD","title":"FIELD","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.AliasMode.JSON","title":"JSON","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.alias_to_classname","title":"alias_to_classname(alias, mode)","text":"

                                    Return class name based dashed or snake alias.

                                    This is applicable creating dynamic wrapper model for a list or dict field.

                                    Source code in trestle/common/str_utils.py
                                    def alias_to_classname(alias: str, mode: AliasMode) -> str:\n\"\"\"\n    Return class name based dashed or snake alias.\n\n    This is applicable creating dynamic wrapper model for a list or dict field.\n    \"\"\"\n    if mode == AliasMode.JSON:\n        return _snake_to_upper_camel(alias.replace('-', '_'))\n    return _snake_to_upper_camel(alias)\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.as_string","title":"as_string(string_or_none)","text":"

                                    Convert string or None to itself or empty string.

                                    Source code in trestle/common/str_utils.py
                                    def as_string(string_or_none: Optional[str]) -> str:\n\"\"\"Convert string or None to itself or empty string.\"\"\"\n    return string_or_none if string_or_none else ''\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.classname_to_alias","title":"classname_to_alias(classname, mode)","text":"

                                    Return oscal key name or field element name based on class name.

                                    This is applicable when asking for a singular element.

                                    Source code in trestle/common/str_utils.py
                                    def classname_to_alias(classname: str, mode: AliasMode) -> str:\n\"\"\"\n    Return oscal key name or field element name based on class name.\n\n    This is applicable when asking for a singular element.\n    \"\"\"\n    suffix = classname.split('.')[-1]\n\n    # the alias mode is either json or field - yaml doesn't apply here\n    if mode == AliasMode.JSON:\n        # things like class_ should just be class\n        if suffix[-1] == '_':\n            suffix = suffix[:-1]\n        return _camel_to_dash(suffix).rstrip(string.digits)\n    # else alias mode is field\n    return _camel_to_snake(suffix).rstrip(string.digits)\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.dash_to_underscore","title":"dash_to_underscore(name)","text":"

                                    Convert dash to underscore.

                                    Source code in trestle/common/str_utils.py
                                    def dash_to_underscore(name: str) -> str:\n\"\"\"Convert dash to underscore.\"\"\"\n    return name.replace('-', '_')\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.spaces_and_caps_to_lower_single_spaces","title":"spaces_and_caps_to_lower_single_spaces(spaced_str)","text":"

                                    Convert caps and duplicate spaces to lower with single spaces.

                                    Source code in trestle/common/str_utils.py
                                    def spaces_and_caps_to_lower_single_spaces(spaced_str: str) -> str:\n\"\"\"Convert caps and duplicate spaces to lower with single spaces.\"\"\"\n    single_space = ' '.join(spaced_str.strip().split())\n    return single_space.lower()\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.spaces_and_caps_to_snake","title":"spaces_and_caps_to_snake(spaced_str)","text":"

                                    Convert caps and spaces to snake.

                                    Source code in trestle/common/str_utils.py
                                    def spaces_and_caps_to_snake(spaced_str: str) -> str:\n\"\"\"Convert caps and spaces to snake.\"\"\"\n    underscored = '_'.join(spaced_str.strip().split())\n    return underscored.lower()\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.string_from_root","title":"string_from_root(item_with_root)","text":"

                                    Convert root to string if present.

                                    Source code in trestle/common/str_utils.py
                                    def string_from_root(item_with_root: Optional[Any]) -> str:\n\"\"\"Convert root to string if present.\"\"\"\n    return as_string(item_with_root.__root__) if item_with_root else ''\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.strip_lower_equals","title":"strip_lower_equals(str_a, str_b)","text":"

                                    Safe test of lower string equality allowing Nones.

                                    If either argument is None the result is False because the intent is to report if they are equal as actual strings.

                                    Source code in trestle/common/str_utils.py
                                    def strip_lower_equals(str_a: Optional[str], str_b: Optional[str]) -> bool:\n\"\"\"\n    Safe test of lower string equality allowing Nones.\n\n    If either argument is None the result is False because the intent is to report if they are equal as actual strings.\n    \"\"\"\n    if str_a is None or str_b is None:\n        return False\n    return str_a.strip().lower() == str_b.strip().lower()\n
                                    "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.underscore_to_dash","title":"underscore_to_dash(name)","text":"

                                    Convert underscore to dash and drop final dash if present.

                                    Source code in trestle/common/str_utils.py
                                    def underscore_to_dash(name: str) -> str:\n\"\"\"Convert underscore to dash and drop final dash if present.\"\"\"\n    converted = name.replace('_', '-')\n    return converted if converted[-1] != '-' else converted[:-1]\n
                                    "},{"location":"api_reference/trestle.common.trash/","title":"trash","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash","title":"trestle.common.trash","text":"

                                    Trestle trash module.

                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.TRESTLE_TRASH_DIR","title":"TRESTLE_TRASH_DIR","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.TRESTLE_TRASH_DIR_EXT","title":"TRESTLE_TRASH_DIR_EXT","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.TRESTLE_TRASH_FILE_EXT","title":"TRESTLE_TRASH_FILE_EXT","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.get_trash_root","title":"get_trash_root(path)","text":"

                                    Find the trestle trash root path.

                                    Source code in trestle/common/trash.py
                                    def get_trash_root(path: pathlib.Path) -> Optional[pathlib.Path]:\n\"\"\"Find the trestle trash root path.\"\"\"\n    if path is None or len(path.parts) <= 0:\n        return None\n\n    current = path\n    while len(current.parts) > 1:  # it must not be the system root directory\n        trash_dir = current / TRESTLE_TRASH_DIR\n        if trash_dir.exists() and trash_dir.is_dir():\n            return trash_dir\n        current = current.parent\n\n    return None\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.has_parent_path","title":"has_parent_path(sub_path, parent_path)","text":"

                                    Check if sub_path has the specified parent_dir path.

                                    Source code in trestle/common/trash.py
                                    def has_parent_path(sub_path: pathlib.Path, parent_path: pathlib.Path) -> bool:\n\"\"\"Check if sub_path has the specified parent_dir path.\"\"\"\n    # sub_path should be longer than parent path\n    if len(sub_path.parts) < len(parent_path.parts):\n        return False\n\n    for i, part in enumerate(parent_path.parts):\n        if part != sub_path.parts[i]:\n            return False\n    return True\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.recover","title":"recover(dest_content_path, delete_trash=False)","text":"

                                    Recover the specified file or directory from the trash directory.

                                    dest_content_path: destination content path that needs to be recovered from trash It recovers the latest path content from trash if exists

                                    Source code in trestle/common/trash.py
                                    def recover(dest_content_path: pathlib.Path, delete_trash: bool = False) -> None:\n\"\"\"Recover the specified file or directory from the trash directory.\n\n    dest_content_path: destination content path that needs to be recovered from trash\n    It recovers the latest path content from trash if exists\n    \"\"\"\n    if dest_content_path.suffix != '':\n        return recover_file(dest_content_path, delete_trash)\n    return recover_dir(dest_content_path, delete_trash)\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.recover_dir","title":"recover_dir(dest_dir_path, delete_trash=False)","text":"

                                    Move the specified dir from the trash directory.

                                    dest_dir_path: destination path of the directory inside a trestle workspace

                                    It recovers the latest directory and contents from trash if exists

                                    Source code in trestle/common/trash.py
                                    def recover_dir(dest_dir_path: pathlib.Path, delete_trash: bool = False) -> None:\n\"\"\"Move the specified dir from the trash directory.\n\n    dest_dir_path: destination path of the directory inside a trestle workspace\n\n    It recovers the latest directory and contents from trash if exists\n    \"\"\"\n    trash_dir_path = to_trash_dir_path(dest_dir_path)\n    if not (trash_dir_path.exists() and trash_dir_path.is_dir()):\n        raise AssertionError(f'Specified path \"{dest_dir_path}\" could not be found in trash')\n\n    # move all files/directories under sub_path\n    for item_path in pathlib.Path.iterdir(trash_dir_path):\n        if item_path.is_file():\n            recover_file(to_origin_file_path(item_path), delete_trash)\n        elif item_path.is_dir():\n            recover_dir(to_origin_dir_path(item_path), delete_trash)\n\n    if delete_trash:\n        trash_dir_path.rmdir()\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.recover_file","title":"recover_file(file_path, delete_trash=False)","text":"

                                    Recover the specified file from the trash directory.

                                    It recovers the latest file from trash if exists

                                    Source code in trestle/common/trash.py
                                    def recover_file(file_path: pathlib.Path, delete_trash: bool = False) -> None:\n\"\"\"Recover the specified file from the trash directory.\n\n    It recovers the latest file from trash if exists\n    \"\"\"\n    trash_file_path = to_trash_file_path(file_path)\n    if not trash_file_path.exists():\n        raise AssertionError(f'Specified path \"{file_path}\" could not be found in trash')\n\n    file_path.parent.mkdir(exist_ok=True, parents=True)\n    copyfile(trash_file_path, file_path)\n\n    if delete_trash:\n        trash_file_path.unlink()\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.store","title":"store(content_path, delete_content=False)","text":"

                                    Move the specified file or directory to the trash directory.

                                    It overwrites the previous file or directory if exists

                                    Source code in trestle/common/trash.py
                                    def store(content_path: pathlib.Path, delete_content: bool = False) -> None:\n\"\"\"Move the specified file or directory to the trash directory.\n\n    It overwrites the previous file or directory if exists\n    \"\"\"\n    if content_path.is_file():\n        return store_file(content_path, delete_content)\n    if content_path.is_dir():\n        return store_dir(content_path, delete_content)\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.store_dir","title":"store_dir(dir_path, delete_source=False)","text":"

                                    Move the specified dir to the trash directory.

                                    It overwrites the previous directory and contents if exists

                                    Source code in trestle/common/trash.py
                                    def store_dir(dir_path: pathlib.Path, delete_source: bool = False) -> None:\n\"\"\"Move the specified dir to the trash directory.\n\n    It overwrites the previous directory and contents if exists\n    \"\"\"\n    if not dir_path.is_dir():\n        raise AssertionError(f'Specified path \"{dir_path}\" is not a dir')\n\n    # move all files/directories under sub_path\n    for item_path in pathlib.Path.iterdir(dir_path):\n        if item_path.is_file():\n            store_file(item_path, delete_source)\n        elif item_path.is_dir():\n            store_dir(item_path, delete_source)\n\n    if delete_source:\n        dir_path.rmdir()\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.store_file","title":"store_file(file_path, delete_source=False)","text":"

                                    Move the specified file to the trash directory.

                                    It overwrites the previous file if exists

                                    Source code in trestle/common/trash.py
                                    def store_file(file_path: pathlib.Path, delete_source: bool = False) -> None:\n\"\"\"Move the specified file to the trash directory.\n\n    It overwrites the previous file if exists\n    \"\"\"\n    if not file_path.is_file():\n        raise AssertionError(f'Specified path \"{file_path}\" is not a file')\n\n    trash_file_path = to_trash_file_path(file_path)\n    trash_file_path.parent.mkdir(exist_ok=True, parents=True)\n    copyfile(file_path, trash_file_path)\n\n    if delete_source:\n        file_path.unlink()\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_origin_dir_path","title":"to_origin_dir_path(trash_dir_path)","text":"

                                    Convert trash content path to origin path.

                                    Source code in trestle/common/trash.py
                                    def to_origin_dir_path(trash_dir_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert trash content path to origin path.\"\"\"\n    if trash_dir_path.suffix != '' and trash_dir_path.suffix.endswith(TRESTLE_TRASH_FILE_EXT):\n        raise AssertionError(f'Given path \"{trash_dir_path}\" is a trash file, not a valid trash directory')\n\n    trestle_root = file_utils.extract_trestle_project_root(trash_dir_path)\n    if trestle_root is None:\n        raise AssertionError(f'Directory path \"{trash_dir_path}\" is not in a valid trestle project path')\n\n    trash_root = get_trash_root(trash_dir_path)\n    if trash_root is None:\n        raise AssertionError(f'Directory path \"{trash_dir_path}\" is not in a valid trestle trash path')\n\n    if not has_parent_path(trash_dir_path, trash_root):\n        raise AssertionError(f'Directory path \"{trash_dir_path}\" is not a valid trash dir path')\n\n    relative_path = trash_dir_path.relative_to(str(trash_root))\n\n    origin_path_parts: List[str] = []\n    for item in relative_path.parts:\n        parts = item.split(TRESTLE_TRASH_DIR_EXT)\n        origin_path_parts.append(parts[0])\n\n    origin_relative_path = pathlib.Path('/'.join(origin_path_parts))\n    origin_path = trestle_root / origin_relative_path\n    return origin_path\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_origin_file_path","title":"to_origin_file_path(trash_file_path)","text":"

                                    Convert trash file path to origin file path.

                                    Source code in trestle/common/trash.py
                                    def to_origin_file_path(trash_file_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert trash file path to origin file path.\"\"\"\n    if trash_file_path.suffix != TRESTLE_TRASH_FILE_EXT:\n        raise AssertionError(f'File path \"{trash_file_path}\" is not a valid trash file path')\n\n    origin_dir = to_origin_dir_path(trash_file_path.parent)\n    file_parts = trash_file_path.name.split(TRESTLE_TRASH_FILE_EXT)\n    origin_file_path = origin_dir / file_parts[0]\n\n    return origin_file_path\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_origin_path","title":"to_origin_path(trash_content_path)","text":"

                                    Convert the trash path to origin path.

                                    Source code in trestle/common/trash.py
                                    def to_origin_path(trash_content_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert the trash path to origin path.\"\"\"\n    if trash_content_path.suffix == TRESTLE_TRASH_FILE_EXT:\n        return to_origin_file_path(trash_content_path)\n    return to_origin_dir_path(trash_content_path)\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_trash_dir_path","title":"to_trash_dir_path(dir_path)","text":"

                                    Construct the path to the trashed file.

                                    Source code in trestle/common/trash.py
                                    def to_trash_dir_path(dir_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Construct the path to the trashed file.\"\"\"\n    absolute_path = dir_path.resolve()\n    root_path = file_utils.extract_trestle_project_root(absolute_path)\n    if root_path is None:\n        raise AssertionError(f'Directory path \"{absolute_path}\" is not in a valid trestle project')\n\n    trestle_trash_path = root_path / TRESTLE_TRASH_DIR\n\n    relative_path = absolute_path.relative_to(str(root_path))\n    if len(relative_path.parts) == 0:\n        trash_dir = trestle_trash_path\n    else:\n        trash_dir = trestle_trash_path / f'{relative_path}{TRESTLE_TRASH_DIR_EXT}'\n\n    return trash_dir\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_trash_file_path","title":"to_trash_file_path(file_path)","text":"

                                    Construct the path to the trashed file.

                                    Source code in trestle/common/trash.py
                                    def to_trash_file_path(file_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Construct the path to the trashed file.\"\"\"\n    trash_file_dir = to_trash_dir_path(file_path.parent)\n    trash_file_path = trash_file_dir / f'{file_path.name}{TRESTLE_TRASH_FILE_EXT}'\n\n    return trash_file_path\n
                                    "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_trash_path","title":"to_trash_path(path)","text":"

                                    Convert the dir or file path to apporpriate trash file or dir path.

                                    Source code in trestle/common/trash.py
                                    def to_trash_path(path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert the dir or file path to apporpriate trash file or dir path.\"\"\"\n    if path.suffix != '':\n        return to_trash_file_path(path)\n    return to_trash_dir_path(path)\n
                                    "},{"location":"api_reference/trestle.common.type_utils/","title":"type_utils","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils","title":"trestle.common.type_utils","text":"

                                    Utilities for dealing with models.

                                    "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.get_inner_type","title":"get_inner_type(collection_field_type)","text":"

                                    Get the inner model in a generic collection model such as a List or a Dict.

                                    For a dict the return type is of the value and not the key.

                                    Parameters:

                                    Name Type Description Default collection_field_type Union[Type[List[Any]], Type[Dict[str, Any]]]

                                    Provided type annotation from a pydantic object

                                    required

                                    Returns:

                                    Type Description Type[Any]

                                    The desired type.

                                    Source code in trestle/common/type_utils.py
                                    def get_inner_type(collection_field_type: Union[Type[List[Any]], Type[Dict[str, Any]]]) -> Type[Any]:\n\"\"\"Get the inner model in a generic collection model such as a List or a Dict.\n\n    For a dict the return type is of the value and not the key.\n\n    Args:\n        collection_field_type: Provided type annotation from a pydantic object\n\n    Returns:\n        The desired type.\n    \"\"\"\n    try:\n        # Pydantic special cases must be dealt with here:\n        _, _, singular_type = _get_model_field_info(collection_field_type)\n        if singular_type is not None:\n            return singular_type\n        return typing_extensions.get_args(collection_field_type)[-1]\n    except Exception as e:\n        logger.debug(e)\n        raise err.TrestleError('Model type is not a Dict or List') from e\n
                                    "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.get_origin","title":"get_origin(field_type)","text":"

                                    Generalized and robust get_origin function.

                                    This function is derived from work by pydantic, however, avoids complications from various python versions.

                                    Source code in trestle/common/type_utils.py
                                    def get_origin(field_type: Type[Any]) -> Optional[Type[Any]]:\n\"\"\"Generalized and robust get_origin function.\n\n    This function is derived from work by pydantic, however, avoids complications\n    from various python versions.\n    \"\"\"\n    # This executes a fallback that allows a list to be generated from a constrained list.\n    return typing_extensions.get_origin(field_type) or getattr(field_type, '__origin__', None)\n
                                    "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.is_collection_field_type","title":"is_collection_field_type(field_type)","text":"

                                    Check whether a type hint is a collection type as used by OSCAL.

                                    Specifically this is whether the type is a list or not.

                                    Parameters:

                                    Name Type Description Default field_type Type[Any]

                                    A type or a type alias of a field typically as served via pydantic introspection

                                    required

                                    Returns:

                                    Type Description bool

                                    True if it is a collection type list.

                                    Source code in trestle/common/type_utils.py
                                    def is_collection_field_type(field_type: Type[Any]) -> bool:\n\"\"\"Check whether a type hint is a collection type as used by OSCAL.\n\n    Specifically this is whether the type is a list or not.\n\n    Args:\n        field_type: A type or a type alias of a field typically as served via pydantic introspection\n\n    Returns:\n        True if it is a collection type list.\n    \"\"\"\n    # first check if it is a pydantic __root__ object\n    _, root_type, _ = _get_model_field_info(field_type)\n    if root_type == 'List':\n        return True\n    # Retrieves type from a type annotation\n    origin_type = get_origin(field_type)\n    return origin_type == list\n
                                    "},{"location":"api_reference/trestle.core.all_validator/","title":"all_validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator","title":"trestle.core.all_validator","text":"

                                    Validate based on all registered validators.

                                    "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator","title":" AllValidator (Validator) ","text":"

                                    Validator to confirm the model passes all registered validation tests.

                                    Source code in trestle/core/all_validator.py
                                    class AllValidator(Validator):\n\"\"\"Validator to confirm the model passes all registered validation tests.\"\"\"\n\n    last_failure_msg: str\n\n    def error_msg(self) -> str:\n\"\"\"Return information on which validation failed.\"\"\"\n        return self.last_failure_msg\n\n    def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n        Validate an oscal model against all available validators in the trestle library.\n\n        args:\n            model: An Oscal model that can be passed to the validator.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if the model passed all registered validators.\n        \"\"\"\n        self.last_failure_msg = self.__doc__\n        for val in vfact.validator_factory.get_all():\n            if val != self and not val.model_is_valid(model, quiet, trestle_root):\n                self.last_failure_msg = val.error_msg()\n                return False\n        return True\n
                                    "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator.error_msg","title":"error_msg(self)","text":"

                                    Return information on which validation failed.

                                    Source code in trestle/core/all_validator.py
                                    def error_msg(self) -> str:\n\"\"\"Return information on which validation failed.\"\"\"\n    return self.last_failure_msg\n
                                    "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                    Validate an oscal model against all available validators in the trestle library.

                                    Parameters:

                                    Name Type Description Default model OscalBaseModel

                                    An Oscal model that can be passed to the validator.

                                    required quiet bool

                                    Don't report msgs unless invalid.

                                    required

                                    Returns:

                                    Type Description bool

                                    True (valid) if the model passed all registered validators.

                                    Source code in trestle/core/all_validator.py
                                    def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n    Validate an oscal model against all available validators in the trestle library.\n\n    args:\n        model: An Oscal model that can be passed to the validator.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if the model passed all registered validators.\n    \"\"\"\n    self.last_failure_msg = self.__doc__\n    for val in vfact.validator_factory.get_all():\n        if val != self and not val.model_is_valid(model, quiet, trestle_root):\n            self.last_failure_msg = val.error_msg()\n            return False\n    return True\n
                                    "},{"location":"api_reference/trestle.core.base_model/","title":"base_model","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model","title":"trestle.core.base_model","text":"

                                    Pydantic base model for use within a trestle workspace and associated configuration.

                                    The heart of the current OSCAL model within trestle is based on pydantic (https://pydantic-docs.helpmanual.io/) which itself is a veneer on-top of python data classes.

                                    Functionality here defines a base-model which all trestle oscal data models inherit from. This allows additional functionality to be easily inserted.

                                    I can write a comment in here and you can even edit on the same line.

                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel","title":" OscalBaseModel (TrestleBaseModel) pydantic-model","text":"

                                    Trestle defined pydantic base model for use with OSCAL pydantic dataclasses.

                                    This BaseModel provides two types of functionality: 1. Overrides default configuation of the pydantic library with behaviours required for trestle 2. Provides utility functions for trestle which are specific to OSCAL and the naming schema associated with it.

                                    Source code in trestle/core/base_model.py
                                    class OscalBaseModel(TrestleBaseModel):\n\"\"\"\n    Trestle defined pydantic base model for use with OSCAL pydantic dataclasses.\n\n    This BaseModel provides two types of functionality:\n    1. Overrides default configuation of the pydantic library with behaviours required for trestle\n    2. Provides utility functions for trestle which are specific to OSCAL and the naming schema associated with it.\n    \"\"\"\n\n    class Config:\n\"\"\"Overriding configuration class for pydantic base model, for use with OSCAL data classes.\"\"\"\n\n        json_loads = orjson.loads\n        # TODO: json_dumps with orjson.dumps see #840\n\n        json_encoders = {datetime.datetime: lambda x: robust_datetime_serialization(x)}\n        allow_population_by_field_name = True\n\n        # Enforce strict schema\n        extra = Extra.forbid\n\n        # Validate on assignment of variables to ensure no escapes\n        validate_assignment = True\n\n    @classmethod\n    def create_stripped_model_type(\n        cls,\n        stripped_fields: Optional[List[str]] = None,\n        stripped_fields_aliases: Optional[List[str]] = None\n    ) -> Type['OscalBaseModel']:\n\"\"\"Create a pydantic model, which is derived from the current model, but missing certain fields.\n\n        OSCAL mandates a 'strict' schema (e.g. unless otherwise stated no additional fields), and certain fields\n        are mandatory. Given this the corresponding dataclasses are also strict. Workflows with trestle require missing\n        mandatory fields. This allows creation of derivative models missing certain fields.\n\n        Args:\n            stripped_fields: The fields to be removed from the current data class.\n            stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n        Returns:\n            Pydantic data class thta can be used to instanciate a model.\n\n        Raises:\n            TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n            TrestleError: If incorrect aliases or field names are provided.\n        \"\"\"\n        if stripped_fields is not None and stripped_fields_aliases is not None:\n            raise err.TrestleError('Either \"stripped_fields\" or \"stripped_fields_aliases\" need to be passed, not both.')\n        if stripped_fields is None and stripped_fields_aliases is None:\n            raise err.TrestleError('Exactly one of \"stripped_fields\" or \"stripped_fields_aliases\" must be provided')\n\n        # create alias to field_name mapping\n        excluded_fields = []\n        if stripped_fields is not None:\n            excluded_fields = stripped_fields\n        elif stripped_fields_aliases is not None:\n            alias_to_field = cls.alias_to_field_map()\n            try:\n                excluded_fields = [alias_to_field[key].name for key in stripped_fields_aliases]\n            except KeyError as e:\n                raise err.TrestleError(f'Field {str(e)} does not exist in the model')\n\n        current_fields = cls.__fields__\n        new_fields_for_model = {}\n        # Build field list\n        for current_mfield in current_fields.values():\n            if current_mfield.name in excluded_fields:\n                continue\n            # Validate name in the field\n            # Cehcke behaviour with an alias\n            if current_mfield.required:\n                new_fields_for_model[\n                    current_mfield.name\n                ] = (current_mfield.outer_type_, Field(..., title=current_mfield.name, alias=current_mfield.alias))\n            else:\n                new_fields_for_model[current_mfield.name] = (\n                    Optional[current_mfield.outer_type_],\n                    Field(None, title=current_mfield.name, alias=current_mfield.alias)\n                )\n        new_model = create_model(cls.__name__, __base__=OscalBaseModel, **new_fields_for_model)  # type: ignore\n        # TODO: This typing cast should NOT be necessary. Potentially fixable with a fix to pydantic. Issue #175\n        new_model = cast(Type[OscalBaseModel], new_model)\n\n        return new_model\n\n    def get_field_by_alias(self, field_alias: str) -> Any:\n\"\"\"Convert field alias to a field.\"\"\"\n        attr_field = self.alias_to_field_map().get(field_alias, None)\n        return attr_field\n\n    def get_field_value_by_alias(self, attr_alias: str) -> Optional[Any]:\n\"\"\"Get attribute value by field alias.\"\"\"\n        # TODO: can this be restricted beyond Any easily.\n        attr_field = self.get_field_by_alias(attr_alias)\n        if isinstance(attr_field, ModelField):\n            return getattr(self, attr_field.name, None)\n\n        return None\n\n    def stripped_instance(\n        self,\n        stripped_fields: Optional[List[str]] = None,\n        stripped_fields_aliases: Optional[List[str]] = None\n    ) -> 'OscalBaseModel':\n\"\"\"Return a new model instance with the specified fields being stripped.\n\n        Args:\n            stripped_fields: The fields to be removed from the current data class.\n            stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n        Returns:\n            The current datamodel with the fields provided removed in a derivate (run time created) data model.\n\n        Raises:\n            err.TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n            err.TrestleError: If incorrect aliases or field names are provided.\n        \"\"\"\n        # stripped class type\n        stripped_class: Type[OscalBaseModel] = self.create_stripped_model_type(\n            stripped_fields=stripped_fields, stripped_fields_aliases=stripped_fields_aliases\n        )\n\n        # remaining values\n        remaining_values = {}\n        for field in self.__fields__.values():\n            if field.name in stripped_class.__fields__:\n                remaining_values[field.name] = self.__dict__[field.name]\n\n        # create stripped model instance\n        # TODO: Not sure if we can avoid type escapes here\n        stripped_instance = stripped_class(**remaining_values)\n\n        return stripped_instance\n\n    def oscal_dict(self) -> Dict[str, Any]:\n\"\"\"Return a dictionary including the root wrapping object key.\"\"\"\n        class_name = self.__class__.__name__\n        result = {}\n        raw_dict = self.dict(by_alias=True, exclude_none=True)\n        # Additional check to avoid root serialization\n        if '__root__' in raw_dict.keys():\n            result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict['__root__']\n        else:\n            result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict\n        return result\n\n    def oscal_serialize_json_bytes(self, pretty: bool = False, wrapped: bool = True) -> bytes:\n\"\"\"\n        Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n        Args:\n            pretty: Whether or not to pretty-print json output or have in compressed form.\n        Returns:\n            Oscal model serialized to a json object including packaging inside of a single top level key.\n        \"\"\"\n        if wrapped:\n            odict = self.oscal_dict()\n        else:\n            odict = self.dict(by_alias=True, exclude_none=True)\n        if pretty:\n            return orjson.dumps(odict, default=self.__json_encoder__, option=orjson.OPT_INDENT_2)  # type: ignore\n        return orjson.dumps(odict, default=self.__json_encoder__)  # type: ignore\n\n    def oscal_serialize_json(self, pretty: bool = False, wrapped: bool = True) -> str:\n\"\"\"\n        Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n        Args:\n            pretty: Whether or not to pretty-print json output or have in compressed form.\n        Returns:\n            Oscal model serialized to a json object including packaging inside of a single top level key.\n        \"\"\"\n        # This function is provided for backwards compatibility\n        return self.oscal_serialize_json_bytes(pretty, wrapped).decode(const.FILE_ENCODING)\n\n    def oscal_write(self, path: pathlib.Path) -> None:\n\"\"\"\n        Write out a pydantic data model in an oscal friendly way.\n\n        OSCAL schema mandates that top level elements are wrapped in a singular\n        json/yaml field. This function handles both json and yaml output as well\n        as formatting of the json.\n\n        Args:\n            path: The output file location for the oscal object.\n\n        Raises:\n            err.TrestleError: If a unknown file extension is provided.\n        \"\"\"\n        content_type = FileContentType.to_content_type(path.suffix)\n        # The output will have \\r\\n newlines on windows and \\n newlines elsewhere\n\n        if content_type == FileContentType.YAML:\n            write_file = pathlib.Path(path).open('w', encoding=const.FILE_ENCODING)\n            yaml = YAML(typ='safe')\n            yaml.dump(yaml.load(self.oscal_serialize_json()), write_file)\n            write_file.flush()\n            write_file.close()\n        elif content_type == FileContentType.JSON:\n            write_file = pathlib.Path(path).open('wb')  # type: ignore\n            write_file.write(self.oscal_serialize_json_bytes(pretty=True))  # type: ignore\n            # Flush / close required (by experience) due to flushing issues in tests.\n            write_file.flush()\n            write_file.close()\n\n    @classmethod\n    def oscal_read(cls, path: pathlib.Path) -> Optional['OscalBaseModel']:\n\"\"\"\n        Read OSCAL objects.\n\n        Handles the fact OSCAL wraps top level elements and also deals with both yaml and json.\n\n        Args:\n            path: The path of the oscal object to read.\n        Returns:\n            The oscal object read into trestle oscal models.\n        \"\"\"\n        # Create the wrapper model.\n        alias = classname_to_alias(cls.__name__, AliasMode.JSON)\n\n        content_type = FileContentType.to_content_type(path.suffix)\n        logger.debug(f'oscal_read content type {content_type} and alias {alias} from {path}')\n\n        if not path.exists():\n            logger.warning(f'path does not exist in oscal_read: {path}')\n            return None\n\n        obj: Dict[str, Any] = {}\n        try:\n            if content_type == FileContentType.YAML:\n                yaml = YAML(typ='safe')\n                fh = path.open('r', encoding=const.FILE_ENCODING)\n                obj = yaml.load(fh)\n                fh.close()\n            elif content_type == FileContentType.JSON:\n                obj = load_file(\n                    path,\n                    json_loads=cls.__config__.json_loads,\n                )\n        except Exception as e:\n            raise err.TrestleError(f'Error loading file {path} {str(e)}')\n        try:\n            if not len(obj) == 1:\n                raise err.TrestleError(\n                    f'Invalid OSCAL file structure, oscal file '\n                    f'does not have a single top level key wrapping it. It has {len(obj)} keys.'\n                )\n            parsed = cls.parse_obj(obj[alias])\n        except KeyError:\n            raise err.TrestleError(f'Provided oscal file does not have top level key key: {alias}')\n        except Exception as e:\n            raise err.TrestleError(f'Error parsing file {path} {str(e)}')\n\n        return parsed\n\n    def copy_to(self, new_oscal_type: Type['OscalBaseModel']) -> 'OscalBaseModel':\n\"\"\"\n        Opportunistic copy operation between similar types of data classes.\n\n        Due to the way in which oscal is constructed we get a set of similar / the same definition across various\n        oscal models. Due to the lack of guarantees that they are the same we cannot easily 'collapse' the mode.\n\n        Args:\n            new_oscal_type: The desired type of oscal model\n\n        Returns:\n            Opportunistic copy of the data into the new model type.\n        \"\"\"\n        logger.debug('Copy to started')\n        if self.__class__.__name__ == new_oscal_type.__name__:\n            logger.debug('Json based copy')\n            # Note: Json based oppportunistic copy\n            # Dev notes: Do not change this from json. Due to enums (in particular) json is the closest we can get.\n            return new_oscal_type.parse_raw(self.oscal_serialize_json(pretty=False, wrapped=False))\n\n        if ('__root__' in self.__fields__ and len(self.__fields__) == 1 and '__root__' in new_oscal_type.__fields__\n                and len(new_oscal_type.__fields__) == 1):\n            logger.debug('Root element based copy too')\n            return new_oscal_type.parse_obj(self.__root__)  # type: ignore\n\n        # bad place here.\n        raise err.TrestleError('Provided inconsistent classes to copy to methodology.')\n\n    def copy_from(self, existing_oscal_object: 'OscalBaseModel') -> None:\n\"\"\"\n        Copy operation that implicitly does type conversion.\n\n        Typically would\n        be used to set an attribute, however, does not need to be.\n\n        Deals with two scenarios:\n        1) Casting across oscal models of equivalent type. The purpose if this\n        is to cross class spaces.\n\n        2) The same as above where the item is an array style object which does\n        not correctly serialize to a dict.\n\n        3) if the from and 'to' objects are root schema elements the copy operation\n        will copy the root element to the value.\n\n        Args:\n            existing_oscal_object: The oscal object where fields are copied from.\n\n        \"\"\"\n        recast_object = existing_oscal_object.copy_to(self.__class__)\n        for raw_field in self.__dict__:\n            self.__dict__[raw_field] = recast_object.__dict__[raw_field]\n\n    @classmethod\n    def alias_to_field_map(cls) -> Dict[str, ModelField]:\n\"\"\"Create a map from field alias to field.\n\n        Returns:\n            A dict which has key's of aliases and Fields as values.\n        \"\"\"\n        alias_to_field: Dict[str, ModelField] = {}\n        for field in cls.__fields__.values():\n            alias_to_field[field.alias] = field\n\n        return alias_to_field\n\n    @classmethod\n    def is_collection_container(cls) -> bool:\n\"\"\"\n        Determine whether a pydantic model has being created to wrap a collection primitive (e.g a list or dict).\n\n        In performing model decomposition it is possible using trestle framework to automatically generate a model\n        which looks like\n\n        class Foo(OscalBaseModel):\n            __root__: List[Bar]\n\n        Returns:\n            Boolean on if it meets the above criteria\n\n        When these cases exist we need special handling of the type information.\n        \"\"\"\n        # Additional sanity check on field length\n        if len(cls.__fields__) == 1 and '__root__' in cls.__fields__:\n            # This is now a __root__ key only model\n            if is_collection_field_type(cls.__fields__['__root__'].outer_type_):\n                return True\n        return False\n\n    @classmethod\n    def get_collection_type(cls) -> Optional[type]:\n\"\"\"\n        If the type wraps an collection, return the collection type.\n\n        Returns:\n            The collection type.\n\n        Raises:\n            err.TrestleError: if not a wrapper of the collection type.\n        \"\"\"\n        if not cls.is_collection_container():\n            raise err.TrestleError('OscalBaseModel is not wrapping a collection type')\n        return get_origin(cls.__fields__['__root__'].outer_type_)\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.Config","title":" Config ","text":"

                                    Overriding configuration class for pydantic base model, for use with OSCAL data classes.

                                    Source code in trestle/core/base_model.py
                                    class Config:\n\"\"\"Overriding configuration class for pydantic base model, for use with OSCAL data classes.\"\"\"\n\n    json_loads = orjson.loads\n    # TODO: json_dumps with orjson.dumps see #840\n\n    json_encoders = {datetime.datetime: lambda x: robust_datetime_serialization(x)}\n    allow_population_by_field_name = True\n\n    # Enforce strict schema\n    extra = Extra.forbid\n\n    # Validate on assignment of variables to ensure no escapes\n    validate_assignment = True\n
                                    allow_population_by_field_name \u00a4 extra \u00a4 json_encoders \u00a4 json_loads \u00a4 validate_assignment \u00a4"},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.alias_to_field_map","title":"alias_to_field_map() classmethod","text":"

                                    Create a map from field alias to field.

                                    Returns:

                                    Type Description Dict[str, pydantic.v1.fields.ModelField]

                                    A dict which has key's of aliases and Fields as values.

                                    Source code in trestle/core/base_model.py
                                    @classmethod\ndef alias_to_field_map(cls) -> Dict[str, ModelField]:\n\"\"\"Create a map from field alias to field.\n\n    Returns:\n        A dict which has key's of aliases and Fields as values.\n    \"\"\"\n    alias_to_field: Dict[str, ModelField] = {}\n    for field in cls.__fields__.values():\n        alias_to_field[field.alias] = field\n\n    return alias_to_field\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.copy_from","title":"copy_from(self, existing_oscal_object)","text":"

                                    Copy operation that implicitly does type conversion.

                                    Typically would be used to set an attribute, however, does not need to be.

                                    Deals with two scenarios: 1) Casting across oscal models of equivalent type. The purpose if this is to cross class spaces.

                                    2) The same as above where the item is an array style object which does not correctly serialize to a dict.

                                    3) if the from and 'to' objects are root schema elements the copy operation will copy the root element to the value.

                                    Parameters:

                                    Name Type Description Default existing_oscal_object OscalBaseModel

                                    The oscal object where fields are copied from.

                                    required Source code in trestle/core/base_model.py
                                    def copy_from(self, existing_oscal_object: 'OscalBaseModel') -> None:\n\"\"\"\n    Copy operation that implicitly does type conversion.\n\n    Typically would\n    be used to set an attribute, however, does not need to be.\n\n    Deals with two scenarios:\n    1) Casting across oscal models of equivalent type. The purpose if this\n    is to cross class spaces.\n\n    2) The same as above where the item is an array style object which does\n    not correctly serialize to a dict.\n\n    3) if the from and 'to' objects are root schema elements the copy operation\n    will copy the root element to the value.\n\n    Args:\n        existing_oscal_object: The oscal object where fields are copied from.\n\n    \"\"\"\n    recast_object = existing_oscal_object.copy_to(self.__class__)\n    for raw_field in self.__dict__:\n        self.__dict__[raw_field] = recast_object.__dict__[raw_field]\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.copy_to","title":"copy_to(self, new_oscal_type)","text":"

                                    Opportunistic copy operation between similar types of data classes.

                                    Due to the way in which oscal is constructed we get a set of similar / the same definition across various oscal models. Due to the lack of guarantees that they are the same we cannot easily 'collapse' the mode.

                                    Parameters:

                                    Name Type Description Default new_oscal_type Type[OscalBaseModel]

                                    The desired type of oscal model

                                    required

                                    Returns:

                                    Type Description OscalBaseModel

                                    Opportunistic copy of the data into the new model type.

                                    Source code in trestle/core/base_model.py
                                    def copy_to(self, new_oscal_type: Type['OscalBaseModel']) -> 'OscalBaseModel':\n\"\"\"\n    Opportunistic copy operation between similar types of data classes.\n\n    Due to the way in which oscal is constructed we get a set of similar / the same definition across various\n    oscal models. Due to the lack of guarantees that they are the same we cannot easily 'collapse' the mode.\n\n    Args:\n        new_oscal_type: The desired type of oscal model\n\n    Returns:\n        Opportunistic copy of the data into the new model type.\n    \"\"\"\n    logger.debug('Copy to started')\n    if self.__class__.__name__ == new_oscal_type.__name__:\n        logger.debug('Json based copy')\n        # Note: Json based oppportunistic copy\n        # Dev notes: Do not change this from json. Due to enums (in particular) json is the closest we can get.\n        return new_oscal_type.parse_raw(self.oscal_serialize_json(pretty=False, wrapped=False))\n\n    if ('__root__' in self.__fields__ and len(self.__fields__) == 1 and '__root__' in new_oscal_type.__fields__\n            and len(new_oscal_type.__fields__) == 1):\n        logger.debug('Root element based copy too')\n        return new_oscal_type.parse_obj(self.__root__)  # type: ignore\n\n    # bad place here.\n    raise err.TrestleError('Provided inconsistent classes to copy to methodology.')\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.create_stripped_model_type","title":"create_stripped_model_type(stripped_fields=None, stripped_fields_aliases=None) classmethod","text":"

                                    Create a pydantic model, which is derived from the current model, but missing certain fields.

                                    OSCAL mandates a 'strict' schema (e.g. unless otherwise stated no additional fields), and certain fields are mandatory. Given this the corresponding dataclasses are also strict. Workflows with trestle require missing mandatory fields. This allows creation of derivative models missing certain fields.

                                    Parameters:

                                    Name Type Description Default stripped_fields Optional[List[str]]

                                    The fields to be removed from the current data class.

                                    None stripped_fields_aliases Optional[List[str]]

                                    The fields to be removed from the current data class provided by alias.

                                    None

                                    Returns:

                                    Type Description Type[OscalBaseModel]

                                    Pydantic data class thta can be used to instanciate a model.

                                    Exceptions:

                                    Type Description TrestleError

                                    If user provided both stripped_fields and stripped_field_aliases or neither.

                                    TrestleError

                                    If incorrect aliases or field names are provided.

                                    Source code in trestle/core/base_model.py
                                    @classmethod\ndef create_stripped_model_type(\n    cls,\n    stripped_fields: Optional[List[str]] = None,\n    stripped_fields_aliases: Optional[List[str]] = None\n) -> Type['OscalBaseModel']:\n\"\"\"Create a pydantic model, which is derived from the current model, but missing certain fields.\n\n    OSCAL mandates a 'strict' schema (e.g. unless otherwise stated no additional fields), and certain fields\n    are mandatory. Given this the corresponding dataclasses are also strict. Workflows with trestle require missing\n    mandatory fields. This allows creation of derivative models missing certain fields.\n\n    Args:\n        stripped_fields: The fields to be removed from the current data class.\n        stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n    Returns:\n        Pydantic data class thta can be used to instanciate a model.\n\n    Raises:\n        TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n        TrestleError: If incorrect aliases or field names are provided.\n    \"\"\"\n    if stripped_fields is not None and stripped_fields_aliases is not None:\n        raise err.TrestleError('Either \"stripped_fields\" or \"stripped_fields_aliases\" need to be passed, not both.')\n    if stripped_fields is None and stripped_fields_aliases is None:\n        raise err.TrestleError('Exactly one of \"stripped_fields\" or \"stripped_fields_aliases\" must be provided')\n\n    # create alias to field_name mapping\n    excluded_fields = []\n    if stripped_fields is not None:\n        excluded_fields = stripped_fields\n    elif stripped_fields_aliases is not None:\n        alias_to_field = cls.alias_to_field_map()\n        try:\n            excluded_fields = [alias_to_field[key].name for key in stripped_fields_aliases]\n        except KeyError as e:\n            raise err.TrestleError(f'Field {str(e)} does not exist in the model')\n\n    current_fields = cls.__fields__\n    new_fields_for_model = {}\n    # Build field list\n    for current_mfield in current_fields.values():\n        if current_mfield.name in excluded_fields:\n            continue\n        # Validate name in the field\n        # Cehcke behaviour with an alias\n        if current_mfield.required:\n            new_fields_for_model[\n                current_mfield.name\n            ] = (current_mfield.outer_type_, Field(..., title=current_mfield.name, alias=current_mfield.alias))\n        else:\n            new_fields_for_model[current_mfield.name] = (\n                Optional[current_mfield.outer_type_],\n                Field(None, title=current_mfield.name, alias=current_mfield.alias)\n            )\n    new_model = create_model(cls.__name__, __base__=OscalBaseModel, **new_fields_for_model)  # type: ignore\n    # TODO: This typing cast should NOT be necessary. Potentially fixable with a fix to pydantic. Issue #175\n    new_model = cast(Type[OscalBaseModel], new_model)\n\n    return new_model\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.get_collection_type","title":"get_collection_type() classmethod","text":"

                                    If the type wraps an collection, return the collection type.

                                    Returns:

                                    Type Description Optional[type]

                                    The collection type.

                                    Exceptions:

                                    Type Description err.TrestleError

                                    if not a wrapper of the collection type.

                                    Source code in trestle/core/base_model.py
                                    @classmethod\ndef get_collection_type(cls) -> Optional[type]:\n\"\"\"\n    If the type wraps an collection, return the collection type.\n\n    Returns:\n        The collection type.\n\n    Raises:\n        err.TrestleError: if not a wrapper of the collection type.\n    \"\"\"\n    if not cls.is_collection_container():\n        raise err.TrestleError('OscalBaseModel is not wrapping a collection type')\n    return get_origin(cls.__fields__['__root__'].outer_type_)\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.get_field_by_alias","title":"get_field_by_alias(self, field_alias)","text":"

                                    Convert field alias to a field.

                                    Source code in trestle/core/base_model.py
                                    def get_field_by_alias(self, field_alias: str) -> Any:\n\"\"\"Convert field alias to a field.\"\"\"\n    attr_field = self.alias_to_field_map().get(field_alias, None)\n    return attr_field\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.get_field_value_by_alias","title":"get_field_value_by_alias(self, attr_alias)","text":"

                                    Get attribute value by field alias.

                                    Source code in trestle/core/base_model.py
                                    def get_field_value_by_alias(self, attr_alias: str) -> Optional[Any]:\n\"\"\"Get attribute value by field alias.\"\"\"\n    # TODO: can this be restricted beyond Any easily.\n    attr_field = self.get_field_by_alias(attr_alias)\n    if isinstance(attr_field, ModelField):\n        return getattr(self, attr_field.name, None)\n\n    return None\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.is_collection_container","title":"is_collection_container() classmethod","text":"

                                    Determine whether a pydantic model has being created to wrap a collection primitive (e.g a list or dict).

                                    In performing model decomposition it is possible using trestle framework to automatically generate a model which looks like

                                    class Foo(OscalBaseModel): root: List[Bar]

                                    Returns:

                                    Type Description bool

                                    Boolean on if it meets the above criteria

                                    When these cases exist we need special handling of the type information.

                                    Source code in trestle/core/base_model.py
                                    @classmethod\ndef is_collection_container(cls) -> bool:\n\"\"\"\n    Determine whether a pydantic model has being created to wrap a collection primitive (e.g a list or dict).\n\n    In performing model decomposition it is possible using trestle framework to automatically generate a model\n    which looks like\n\n    class Foo(OscalBaseModel):\n        __root__: List[Bar]\n\n    Returns:\n        Boolean on if it meets the above criteria\n\n    When these cases exist we need special handling of the type information.\n    \"\"\"\n    # Additional sanity check on field length\n    if len(cls.__fields__) == 1 and '__root__' in cls.__fields__:\n        # This is now a __root__ key only model\n        if is_collection_field_type(cls.__fields__['__root__'].outer_type_):\n            return True\n    return False\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_dict","title":"oscal_dict(self)","text":"

                                    Return a dictionary including the root wrapping object key.

                                    Source code in trestle/core/base_model.py
                                    def oscal_dict(self) -> Dict[str, Any]:\n\"\"\"Return a dictionary including the root wrapping object key.\"\"\"\n    class_name = self.__class__.__name__\n    result = {}\n    raw_dict = self.dict(by_alias=True, exclude_none=True)\n    # Additional check to avoid root serialization\n    if '__root__' in raw_dict.keys():\n        result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict['__root__']\n    else:\n        result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict\n    return result\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_read","title":"oscal_read(path) classmethod","text":"

                                    Read OSCAL objects.

                                    Handles the fact OSCAL wraps top level elements and also deals with both yaml and json.

                                    Parameters:

                                    Name Type Description Default path Path

                                    The path of the oscal object to read.

                                    required

                                    Returns:

                                    Type Description Optional[OscalBaseModel]

                                    The oscal object read into trestle oscal models.

                                    Source code in trestle/core/base_model.py
                                    @classmethod\ndef oscal_read(cls, path: pathlib.Path) -> Optional['OscalBaseModel']:\n\"\"\"\n    Read OSCAL objects.\n\n    Handles the fact OSCAL wraps top level elements and also deals with both yaml and json.\n\n    Args:\n        path: The path of the oscal object to read.\n    Returns:\n        The oscal object read into trestle oscal models.\n    \"\"\"\n    # Create the wrapper model.\n    alias = classname_to_alias(cls.__name__, AliasMode.JSON)\n\n    content_type = FileContentType.to_content_type(path.suffix)\n    logger.debug(f'oscal_read content type {content_type} and alias {alias} from {path}')\n\n    if not path.exists():\n        logger.warning(f'path does not exist in oscal_read: {path}')\n        return None\n\n    obj: Dict[str, Any] = {}\n    try:\n        if content_type == FileContentType.YAML:\n            yaml = YAML(typ='safe')\n            fh = path.open('r', encoding=const.FILE_ENCODING)\n            obj = yaml.load(fh)\n            fh.close()\n        elif content_type == FileContentType.JSON:\n            obj = load_file(\n                path,\n                json_loads=cls.__config__.json_loads,\n            )\n    except Exception as e:\n        raise err.TrestleError(f'Error loading file {path} {str(e)}')\n    try:\n        if not len(obj) == 1:\n            raise err.TrestleError(\n                f'Invalid OSCAL file structure, oscal file '\n                f'does not have a single top level key wrapping it. It has {len(obj)} keys.'\n            )\n        parsed = cls.parse_obj(obj[alias])\n    except KeyError:\n        raise err.TrestleError(f'Provided oscal file does not have top level key key: {alias}')\n    except Exception as e:\n        raise err.TrestleError(f'Error parsing file {path} {str(e)}')\n\n    return parsed\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_serialize_json","title":"oscal_serialize_json(self, pretty=False, wrapped=True)","text":"

                                    Return an 'oscal wrapped' json object serialized in a compressed form as bytes.

                                    Parameters:

                                    Name Type Description Default pretty bool

                                    Whether or not to pretty-print json output or have in compressed form.

                                    False

                                    Returns:

                                    Type Description str

                                    Oscal model serialized to a json object including packaging inside of a single top level key.

                                    Source code in trestle/core/base_model.py
                                    def oscal_serialize_json(self, pretty: bool = False, wrapped: bool = True) -> str:\n\"\"\"\n    Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n    Args:\n        pretty: Whether or not to pretty-print json output or have in compressed form.\n    Returns:\n        Oscal model serialized to a json object including packaging inside of a single top level key.\n    \"\"\"\n    # This function is provided for backwards compatibility\n    return self.oscal_serialize_json_bytes(pretty, wrapped).decode(const.FILE_ENCODING)\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_serialize_json_bytes","title":"oscal_serialize_json_bytes(self, pretty=False, wrapped=True)","text":"

                                    Return an 'oscal wrapped' json object serialized in a compressed form as bytes.

                                    Parameters:

                                    Name Type Description Default pretty bool

                                    Whether or not to pretty-print json output or have in compressed form.

                                    False

                                    Returns:

                                    Type Description bytes

                                    Oscal model serialized to a json object including packaging inside of a single top level key.

                                    Source code in trestle/core/base_model.py
                                    def oscal_serialize_json_bytes(self, pretty: bool = False, wrapped: bool = True) -> bytes:\n\"\"\"\n    Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n    Args:\n        pretty: Whether or not to pretty-print json output or have in compressed form.\n    Returns:\n        Oscal model serialized to a json object including packaging inside of a single top level key.\n    \"\"\"\n    if wrapped:\n        odict = self.oscal_dict()\n    else:\n        odict = self.dict(by_alias=True, exclude_none=True)\n    if pretty:\n        return orjson.dumps(odict, default=self.__json_encoder__, option=orjson.OPT_INDENT_2)  # type: ignore\n    return orjson.dumps(odict, default=self.__json_encoder__)  # type: ignore\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_write","title":"oscal_write(self, path)","text":"

                                    Write out a pydantic data model in an oscal friendly way.

                                    OSCAL schema mandates that top level elements are wrapped in a singular json/yaml field. This function handles both json and yaml output as well as formatting of the json.

                                    Parameters:

                                    Name Type Description Default path Path

                                    The output file location for the oscal object.

                                    required

                                    Exceptions:

                                    Type Description err.TrestleError

                                    If a unknown file extension is provided.

                                    Source code in trestle/core/base_model.py
                                    def oscal_write(self, path: pathlib.Path) -> None:\n\"\"\"\n    Write out a pydantic data model in an oscal friendly way.\n\n    OSCAL schema mandates that top level elements are wrapped in a singular\n    json/yaml field. This function handles both json and yaml output as well\n    as formatting of the json.\n\n    Args:\n        path: The output file location for the oscal object.\n\n    Raises:\n        err.TrestleError: If a unknown file extension is provided.\n    \"\"\"\n    content_type = FileContentType.to_content_type(path.suffix)\n    # The output will have \\r\\n newlines on windows and \\n newlines elsewhere\n\n    if content_type == FileContentType.YAML:\n        write_file = pathlib.Path(path).open('w', encoding=const.FILE_ENCODING)\n        yaml = YAML(typ='safe')\n        yaml.dump(yaml.load(self.oscal_serialize_json()), write_file)\n        write_file.flush()\n        write_file.close()\n    elif content_type == FileContentType.JSON:\n        write_file = pathlib.Path(path).open('wb')  # type: ignore\n        write_file.write(self.oscal_serialize_json_bytes(pretty=True))  # type: ignore\n        # Flush / close required (by experience) due to flushing issues in tests.\n        write_file.flush()\n        write_file.close()\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.stripped_instance","title":"stripped_instance(self, stripped_fields=None, stripped_fields_aliases=None)","text":"

                                    Return a new model instance with the specified fields being stripped.

                                    Parameters:

                                    Name Type Description Default stripped_fields Optional[List[str]]

                                    The fields to be removed from the current data class.

                                    None stripped_fields_aliases Optional[List[str]]

                                    The fields to be removed from the current data class provided by alias.

                                    None

                                    Returns:

                                    Type Description OscalBaseModel

                                    The current datamodel with the fields provided removed in a derivate (run time created) data model.

                                    Exceptions:

                                    Type Description err.TrestleError

                                    If user provided both stripped_fields and stripped_field_aliases or neither.

                                    err.TrestleError

                                    If incorrect aliases or field names are provided.

                                    Source code in trestle/core/base_model.py
                                    def stripped_instance(\n    self,\n    stripped_fields: Optional[List[str]] = None,\n    stripped_fields_aliases: Optional[List[str]] = None\n) -> 'OscalBaseModel':\n\"\"\"Return a new model instance with the specified fields being stripped.\n\n    Args:\n        stripped_fields: The fields to be removed from the current data class.\n        stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n    Returns:\n        The current datamodel with the fields provided removed in a derivate (run time created) data model.\n\n    Raises:\n        err.TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n        err.TrestleError: If incorrect aliases or field names are provided.\n    \"\"\"\n    # stripped class type\n    stripped_class: Type[OscalBaseModel] = self.create_stripped_model_type(\n        stripped_fields=stripped_fields, stripped_fields_aliases=stripped_fields_aliases\n    )\n\n    # remaining values\n    remaining_values = {}\n    for field in self.__fields__.values():\n        if field.name in stripped_class.__fields__:\n            remaining_values[field.name] = self.__dict__[field.name]\n\n    # create stripped model instance\n    # TODO: Not sure if we can avoid type escapes here\n    stripped_instance = stripped_class(**remaining_values)\n\n    return stripped_instance\n
                                    "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.robust_datetime_serialization","title":"robust_datetime_serialization(input_dt)","text":"

                                    Return a nicely formatted string for in a format compatible with OSCAL specifications.

                                    Parameters:

                                    Name Type Description Default input_dt datetime

                                    Input datetime to convert to a string.

                                    required

                                    Returns:

                                    Type Description str

                                    String in isoformat to the millisecond enforcing that timezone offset is provided.

                                    Exceptions:

                                    Type Description TrestleError

                                    Error is raised if datetime object does not contain sufficient timezone information.

                                    Source code in trestle/core/base_model.py
                                    def robust_datetime_serialization(input_dt: datetime.datetime) -> str:\n\"\"\"Return a nicely formatted string for in a format compatible with OSCAL specifications.\n\n    Args:\n        input_dt: Input datetime to convert to a string.\n\n    Returns:\n        String in isoformat to the millisecond enforcing that timezone offset is provided.\n\n    Raises:\n        TrestleError: Error is raised if datetime object does not contain sufficient timezone information.\n    \"\"\"\n    # fail if the input datetime is not aware - ie it has no associated timezone\n    if input_dt.tzinfo is None:\n        raise err.TrestleError('Missing timezone in datetime')\n    if input_dt.tzinfo.utcoffset(input_dt) is None:\n        raise err.TrestleError('Missing utcoffset in datetime')\n\n    # use this leave in original timezone rather than utc\n    # return input_dt.astimezone().isoformat(timespec='milliseconds')  noqa: E800\n\n    # force it to be utc\n    return input_dt.astimezone(datetime.timezone.utc).isoformat(timespec='milliseconds')\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/","title":"catalog_api","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api","title":"trestle.core.catalog.catalog_api","text":"

                                    Main entrypoint to interact with catalog in memory.

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI","title":" CatalogAPI ","text":"

                                    Main entrypoint to interact with catalog in memory.

                                    Encapsulates all necessary functionality to manipulate, read and write the catalog and its markdown representation.

                                    Source code in trestle/core/catalog/catalog_api.py
                                    class CatalogAPI():\n\"\"\"\n    Main entrypoint to interact with catalog in memory.\n\n    Encapsulates all necessary functionality to manipulate, read\n    and write the catalog and its markdown representation.\n    \"\"\"\n\n    def __init__(self, catalog: Optional[cat.Catalog], context: Optional[ControlContext] = None):\n\"\"\"Initialize catalog api.\"\"\"\n        if not catalog:\n            # catalog assemble initializes with no catalog but may merge into an existing one later\n            logger.debug('No catalog was provided in CatalogAPI init, generating a new one.')\n            catalog = gens.generate_sample_model(cat.Catalog)\n        self._catalog = catalog\n        self._catalog_interface = CatalogInterface(self._catalog)\n        self._writer = CatalogWriter(self._catalog_interface)\n        self._reader = CatalogReader(self._catalog_interface)\n        self._merger = CatalogMerger(self._catalog_interface)\n        self._context = context\n\n    def update_context(self, context: ControlContext) -> None:\n\"\"\"Update current context.\"\"\"\n        if not context:\n            raise TrestleError('ControlContext cannot be empty.')\n        self._context = context\n\n    def write_catalog_as_markdown(self, label_as_key: bool = False) -> None:\n\"\"\"\n        Write out the catalog controls from dict as markdown files to the specified directory.\n\n        Args:\n            label_as_key: Whether to use label_as_key for part_id to label map\n\n        Returns:\n            None\n        \"\"\"\n        # create the directory in which to write the control markdown files\n        self._context.md_root.mkdir(exist_ok=True, parents=True)\n\n        part_id_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n        if self._context.purpose == ContextPurpose.PROFILE:\n            found_alters, _, _ = self.read_additional_content_from_md(label_as_key=True)\n            self._writer.write_catalog_as_profile_markdown(self._context, part_id_map, found_alters)\n        elif self._context.purpose == ContextPurpose.COMPONENT:\n            self._writer.write_catalog_as_component_markdown(self._context, part_id_map)\n        elif self._context.purpose == ContextPurpose.SSP:\n            self._writer.write_catalog_as_ssp_markdown(self._context, part_id_map)\n        else:\n            self._writer.write_catalog_as_catalog(self._context, part_id_map)\n\n        # prune any directories that have no markdown files\n        prune_empty_dirs(self._context.md_root, '*.md')\n\n    def read_catalog_from_markdown(self, markdown_dir: pathlib.Path, is_set_parameters: bool) -> cat.Catalog:\n\"\"\"Read catalog from markdown.\"\"\"\n        md_catalog = self._reader.read_catalog_from_markdown(markdown_dir, is_set_parameters)\n        md_catalog_interface = CatalogInterface(md_catalog)\n        if md_catalog_interface.get_count_of_controls_in_catalog(True) == 0:\n            raise TrestleError(f'No controls were loaded from markdown {markdown_dir}.  No catalog created.')\n\n        return md_catalog\n\n    def read_additional_content_from_md(self,\n                                        label_as_key: bool = False\n                                        ) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read additional content from markdown.\"\"\"\n        if not self._context:\n            raise TrestleError('Reading content from the markdown requires context to be initialized!')\n        label_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n        return self._reader.read_additional_content(\n            self._context.md_root,\n            self._context.required_sections,\n            label_map,\n            self._context.sections_dict,\n            self._context.to_markdown\n        )\n\n    def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"Merge one catalog into another.\"\"\"\n        return self._merger.merge_catalog(catalog, replace_params)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.__init__","title":"__init__(self, catalog, context=None) special","text":"

                                    Initialize catalog api.

                                    Source code in trestle/core/catalog/catalog_api.py
                                    def __init__(self, catalog: Optional[cat.Catalog], context: Optional[ControlContext] = None):\n\"\"\"Initialize catalog api.\"\"\"\n    if not catalog:\n        # catalog assemble initializes with no catalog but may merge into an existing one later\n        logger.debug('No catalog was provided in CatalogAPI init, generating a new one.')\n        catalog = gens.generate_sample_model(cat.Catalog)\n    self._catalog = catalog\n    self._catalog_interface = CatalogInterface(self._catalog)\n    self._writer = CatalogWriter(self._catalog_interface)\n    self._reader = CatalogReader(self._catalog_interface)\n    self._merger = CatalogMerger(self._catalog_interface)\n    self._context = context\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.merge_catalog","title":"merge_catalog(self, catalog, replace_params)","text":"

                                    Merge one catalog into another.

                                    Source code in trestle/core/catalog/catalog_api.py
                                    def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"Merge one catalog into another.\"\"\"\n    return self._merger.merge_catalog(catalog, replace_params)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.read_additional_content_from_md","title":"read_additional_content_from_md(self, label_as_key=False)","text":"

                                    Read additional content from markdown.

                                    Source code in trestle/core/catalog/catalog_api.py
                                    def read_additional_content_from_md(self,\n                                    label_as_key: bool = False\n                                    ) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read additional content from markdown.\"\"\"\n    if not self._context:\n        raise TrestleError('Reading content from the markdown requires context to be initialized!')\n    label_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n    return self._reader.read_additional_content(\n        self._context.md_root,\n        self._context.required_sections,\n        label_map,\n        self._context.sections_dict,\n        self._context.to_markdown\n    )\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.read_catalog_from_markdown","title":"read_catalog_from_markdown(self, markdown_dir, is_set_parameters)","text":"

                                    Read catalog from markdown.

                                    Source code in trestle/core/catalog/catalog_api.py
                                    def read_catalog_from_markdown(self, markdown_dir: pathlib.Path, is_set_parameters: bool) -> cat.Catalog:\n\"\"\"Read catalog from markdown.\"\"\"\n    md_catalog = self._reader.read_catalog_from_markdown(markdown_dir, is_set_parameters)\n    md_catalog_interface = CatalogInterface(md_catalog)\n    if md_catalog_interface.get_count_of_controls_in_catalog(True) == 0:\n        raise TrestleError(f'No controls were loaded from markdown {markdown_dir}.  No catalog created.')\n\n    return md_catalog\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.update_context","title":"update_context(self, context)","text":"

                                    Update current context.

                                    Source code in trestle/core/catalog/catalog_api.py
                                    def update_context(self, context: ControlContext) -> None:\n\"\"\"Update current context.\"\"\"\n    if not context:\n        raise TrestleError('ControlContext cannot be empty.')\n    self._context = context\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.write_catalog_as_markdown","title":"write_catalog_as_markdown(self, label_as_key=False)","text":"

                                    Write out the catalog controls from dict as markdown files to the specified directory.

                                    Parameters:

                                    Name Type Description Default label_as_key bool

                                    Whether to use label_as_key for part_id to label map

                                    False

                                    Returns:

                                    Type Description None

                                    None

                                    Source code in trestle/core/catalog/catalog_api.py
                                    def write_catalog_as_markdown(self, label_as_key: bool = False) -> None:\n\"\"\"\n    Write out the catalog controls from dict as markdown files to the specified directory.\n\n    Args:\n        label_as_key: Whether to use label_as_key for part_id to label map\n\n    Returns:\n        None\n    \"\"\"\n    # create the directory in which to write the control markdown files\n    self._context.md_root.mkdir(exist_ok=True, parents=True)\n\n    part_id_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n    if self._context.purpose == ContextPurpose.PROFILE:\n        found_alters, _, _ = self.read_additional_content_from_md(label_as_key=True)\n        self._writer.write_catalog_as_profile_markdown(self._context, part_id_map, found_alters)\n    elif self._context.purpose == ContextPurpose.COMPONENT:\n        self._writer.write_catalog_as_component_markdown(self._context, part_id_map)\n    elif self._context.purpose == ContextPurpose.SSP:\n        self._writer.write_catalog_as_ssp_markdown(self._context, part_id_map)\n    else:\n        self._writer.write_catalog_as_catalog(self._context, part_id_map)\n\n    # prune any directories that have no markdown files\n    prune_empty_dirs(self._context.md_root, '*.md')\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/","title":"catalog_interface","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface","title":"trestle.core.catalog.catalog_interface","text":"

                                    Provide interface to catalog allowing queries and operations at control level.

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface","title":" CatalogInterface ","text":"

                                    Interface to query and modify catalog contents.

                                    The catalog is contained in two separate forms: As an actual OSCAL catalog, and as a separate dict providing direct lookup of a control by id.

                                    The two representations should be converted as needed using provided routines: dict -> cat: update_catalog_controls cat -> dict: _create_control_dict

                                    In normal use the dict is created by the CatalogInterface constructor, changes are then made to controls in the dict, then the catalog controls are updated by pulling from the dict back into the catalog.

                                    This class does no direct file i/o. i/o is performed via ControlIO.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    class CatalogInterface():\n\"\"\"\n    Interface to query and modify catalog contents.\n\n    The catalog is contained in two separate forms:  As an actual OSCAL catalog,\n    and as a separate dict providing direct lookup of a control by id.\n\n    The two representations should be converted as needed using provided routines:\n    dict -> cat: update_catalog_controls\n    cat -> dict: _create_control_dict\n\n    In normal use the dict is created by the CatalogInterface constructor,\n    changes are then made to controls in the dict,\n    then the catalog controls are updated by pulling from the dict back into the catalog.\n\n    This class does no direct file i/o.  i/o is performed via ControlIO.\n    \"\"\"\n\n    @dataclass\n    class ControlHandle:\n\"\"\"Convenience class for handling controls as members of a group.\n\n        group_id: id of parent group or '' if not in a group\n        group_title: title of the group\n        group_class: class of the group\n        path: path of parent groups leading to this control - without the final control_id, or [''] if in cat list\n        important to remember that controls may not be in a group and are directly attached to cat\n        control: the control itself\n        \"\"\"\n\n        group_id: str\n        group_title: Optional[str]\n        group_class: Optional[str]\n        group_path: List[str]\n        control_path: List[str]\n        control: cat.Control\n\n    def __init__(self, catalog: Optional[cat.Catalog] = None) -> None:\n\"\"\"Initialize the interface with the catalog.\"\"\"\n        self._catalog = catalog\n        self._param_control_map: Dict[str, str] = {}\n        self._generate_group_index: int = 0\n        self._control_dict = self._create_control_dict() if catalog else None\n        self.loose_param_dict: Dict[str, common.Parameter] = {param.id: param\n                                                              for param in as_list(catalog.params)} if catalog else {}\n        # map control id to CompDict\n        self._control_comp_dicts: Dict[str, CompDict] = {}\n        # map control id to dict containing set parameters by component\n        self._control_comp_set_params: Dict[str, Dict[str, comp.SetParameter]] = {}\n\n    def add_comp_info(self, control_id: str, comp_name: str, label: str, comp_info: ComponentImpInfo) -> None:\n\"\"\"Add comp_info for a control.\"\"\"\n        deep_set(self._control_comp_dicts, [control_id, comp_name, label], comp_info)\n\n    def get_comp_info(self, control_id: str) -> CompDict:\n\"\"\"Get comp_dict for this control.\"\"\"\n        return self._control_comp_dicts.get(control_id, {})\n\n    def clear_comp_dicts(self) -> None:\n\"\"\"Clear the control component dicts.\"\"\"\n        self._control_comp_dicts = {}\n\n    def add_comp_set_param(self, control_id: str, comp_name: str, set_param: comp.SetParameter) -> None:\n\"\"\"Add component setparam for control with overwrite.\"\"\"\n        deep_append(self._control_comp_set_params, [control_id, comp_name], set_param)\n\n    def get_control_comp_set_params(self, control_id: str) -> Dict[str, List[comp.SetParameter]]:\n\"\"\"Get dict of setparams list per component.\"\"\"\n        return self._control_comp_set_params.get(control_id, {})\n\n    def clear_set_params(self) -> None:\n\"\"\"Clear the control set params.\"\"\"\n        self._control_comp_set_params = {}\n\n    def _generate_group_id(self, group: cat.Group) -> str:\n\"\"\"Generate sequential group ids.\"\"\"\n        group_id = f'trestle_group_{self._generate_group_index:04d}'\n        self._generate_group_index += 1\n        logger.warning(f'Group titled \"{group.title}\" has no id and has been assigned id: {group_id}')\n        return group_id\n\n    def _add_params_to_map(self, control: cat.Control) -> None:\n        # this does not need to recurse because it is called for each control in the catalog\n        for param in as_list(control.params):\n            if param.id in self._param_control_map:\n                logger.warning(\n                    f'Duplicate param id {param.id} in control {control.id} and {self._param_control_map[param.id]}.'\n                )\n            self._param_control_map[param.id] = control.id\n\n    def _add_sub_controls(\n        self, control_handle: ControlHandle, control_dict: Dict[str, ControlHandle], path: List[str]\n    ) -> None:\n\"\"\"\n        Get all controls contained in this control and add it to the growing control dict.\n\n        Add all its sub-controls to the dict recursively.\n        The path does not change because only groups are in the path, and controls cannot contain groups.\n        \"\"\"\n        if control_handle.control.controls:\n            group_id = control_handle.group_id\n            group_title = control_handle.group_title\n            group_class = control_handle.group_class\n            group_path = control_handle.group_path\n            control_path = path[:]\n            control_path.append(control_handle.control.id)\n            for sub_control in control_handle.control.controls:\n                control_handle = CatalogInterface.ControlHandle(\n                    group_id=group_id,\n                    group_title=group_title,\n                    group_class=group_class,\n                    group_path=group_path,\n                    control_path=control_path,\n                    control=sub_control\n                )\n                control_dict[sub_control.id] = control_handle\n                self._add_sub_controls(control_handle, control_dict, control_path)\n\n    def _add_group_controls(self, group: cat.Group, control_dict: Dict[str, ControlHandle], path: List[str]) -> None:\n\"\"\"Add all controls in the group recursively, including sub groups and sub controls.\"\"\"\n        group.id = self._generate_group_id(group) if group.id is None else group.id\n        if group.controls is not None:\n            group_path = path[:]\n            if not group_path or group_path[-1] != group.id:\n                group_path.append(group.id)\n            for control in group.controls:\n                control_handle = CatalogInterface.ControlHandle(\n                    group_id=group.id,\n                    group_title=group.title,\n                    group_class=group.class_,\n                    control=control,\n                    group_path=group_path,\n                    control_path=group_path\n                )\n                control_dict[control.id] = control_handle\n                self._add_sub_controls(control_handle, control_dict, group_path)\n        if group.groups is not None:\n            group_path = path[:]\n            group_path.append(group.id)\n            for sub_group in group.groups:\n                new_path = group_path[:]\n                sub_group.id = self._generate_group_id(sub_group) if sub_group.id is None else sub_group.id\n                new_path.append(sub_group.id)\n                self._add_group_controls(sub_group, control_dict, new_path)\n\n    def _create_control_dict(self) -> Dict[str, ControlHandle]:\n        control_dict: Dict[str, CatalogInterface.ControlHandle] = {}\n        # add controls by group\n        if self._catalog.groups is not None:\n            for group in self._catalog.groups:\n                self._add_group_controls(group, control_dict, [])\n        # now add controls not in a group, if any\n        if self._catalog.controls is not None:\n            group_path = ['']\n            for control in self._catalog.controls:\n                control_handle = CatalogInterface.ControlHandle(\n                    group_id='',\n                    group_title='',\n                    group_class=const.MODEL_TYPE_CATALOG,\n                    control=control,\n                    group_path=group_path,\n                    control_path=group_path\n                )\n                control_dict[control.id] = control_handle\n                self._add_sub_controls(control_handle, control_dict, group_path)\n        for handle in control_dict.values():\n            self._add_params_to_map(handle.control)\n        return control_dict\n\n    @staticmethod\n    def _get_all_controls_in_list(controls: List[cat.Control], recurse: bool) -> List[cat.Control]:\n\"\"\"Get all controls in a list with optional recursion for sub controls.\"\"\"\n        new_list: List[cat.Control] = []\n        for control in controls:\n            new_list.append(control)\n            if recurse and control.controls:\n                new_list.extend(CatalogInterface._get_all_controls_in_list(control.controls, recurse))\n        return new_list\n\n    @staticmethod\n    def _get_all_controls_in_group(group: cat.Group, recurse: bool) -> List[cat.Control]:\n\"\"\"\n        Create a list of all controls in this group.\n\n        recurse specifies to recurse within controls, but groups are always recursed\n        \"\"\"\n        controls: List[cat.Control] = []\n        if group.controls:\n            controls.extend(CatalogInterface._get_all_controls_in_list(group.controls, recurse))\n        for sub_group in as_list(group.groups):\n            controls.extend(CatalogInterface._get_all_controls_in_group(sub_group, recurse))\n        return controls\n\n    def get_sorted_controls_in_group(self, group_id: str) -> List[cat.Control]:\n\"\"\"Get the list of controls in a group sorted by the control sort-id.\"\"\"\n        controls: List[cat.Control] = []\n        for control in self.get_all_controls_from_dict():\n            grp_id, _, _ = self.get_group_info_by_control(control.id)\n            if grp_id == group_id:\n                controls.append(control)\n        return sorted(controls, key=lambda control: ControlInterface.get_sort_id(control))\n\n    def get_dependent_control_ids(self, control_id: str) -> List[str]:\n\"\"\"Find all child ids of this control from the dict with recursion.\"\"\"\n        children: List[str] = []\n        control = self.get_control(control_id)\n        if control:\n            new_controls = self._get_all_controls_in_list(as_list(control.controls), True)\n            children.extend([con.id for con in new_controls])\n        return children\n\n    def get_control_ids(self) -> List[str]:\n\"\"\"Get all control ids from the control dict.\"\"\"\n        return self._control_dict.keys()\n\n    def get_control(self, control_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from the control dict with this id.\"\"\"\n        return None if control_id not in self._control_dict else self._control_dict[control_id].control\n\n    @staticmethod\n    def get_control_ids_from_catalog(catalog: cat.Catalog) -> List[str]:\n\"\"\"\n        Get all control ids from a catalog.\n\n        This is intended to provide a quick list of all controls in a catalog without the expense of building the\n        control dict.  So, if repeated queries are made into a catalog, it is worth instantiating a CatalogInterface\n        and associated control dict.  Otherwise just use this to get a list of all controls.\n\n        This function is needed within the CatalogInterface in order to determine if new controls have been added\n        to the dict and need to be inserted in the actual catalog during update.\n        \"\"\"\n        controls = CatalogInterface._get_all_controls_in_list(as_list(catalog.controls), True)\n        id_list = [control.id for control in controls]\n        for group in as_list(catalog.groups):\n            controls = CatalogInterface._get_all_controls_in_group(group, True)\n            id_list.extend([control.id for control in as_list(controls)])\n        return id_list\n\n    def get_control_by_param_id(self, param_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from catalog that has this param id using the dict.\"\"\"\n        if param_id in self._param_control_map:\n            return self.get_control(self._param_control_map[param_id])\n        return None\n\n    def get_control_id_and_status(self, control_name: str) -> Tuple[str, str]:\n\"\"\"\n        Get the control id and status using the control name.\n\n        Returns empty string if status not found.\n        \"\"\"\n        for control in self.get_all_controls_from_dict():\n            if ControlInterface.get_label(control).strip().lower() == control_name.strip().lower():\n                status = ControlInterface.get_prop(control, 'status')\n                return control.id, status\n        return '', ''\n\n    def get_catalog_title(self) -> str:\n\"\"\"Get the title of the catalog.\"\"\"\n        return self._catalog.metadata.title\n\n    def get_statement_part_id_map(self, label_as_key: bool) -> Dict[str, Dict[str, str]]:\n\"\"\"Create mapping of label to part_id for top level parts in statement of all controls.\"\"\"\n        id_map = {}\n        for control in self.get_all_controls_from_catalog(True):\n            statement_part = get_item_from_list(control.parts, const.STATEMENT, lambda p: p.name)\n            if not statement_part:\n                continue\n            id_dict: Dict[str, str] = {}\n            for sub_part in as_list(statement_part.parts):\n                label = ControlInterface.get_label(sub_part)\n                # skip add to map for empty label\n                if not label:\n                    continue\n                if label_as_key:\n                    id_dict[label] = sub_part.id\n                else:\n                    id_dict[sub_part.id] = label\n            if id_dict:\n                id_map[control.id] = id_dict\n        return id_map\n\n    @staticmethod\n    def _get_statement_sub_parts(part: common.Part, indent: int) -> List[Dict[str, str]]:\n        items = []\n        # this may be '' if no label\n        label = ControlInterface.get_label(part)\n        prose = '' if part.prose is None else part.prose\n        items.append({'indent': indent, 'label': label, 'prose': prose})\n        for prt in as_filtered_list(part.parts, lambda p: p.name == const.ITEM):\n            items.extend(CatalogInterface._get_statement_sub_parts(prt, indent + 1))\n        return items\n\n    def get_statement_parts(self, control_id: str) -> List[Dict[str, str]]:\n\"\"\"Get list of statement parts as dicts with indentation, label and prose.\"\"\"\n        items = []\n        control = self.get_control(control_id)\n\n        # control may have no statement or parts\n        # but if statement present it is first part\n        if control is None:\n            logger.warning(f'No control found for id {control_id}')\n        elif control.parts:\n            part = control.parts[0]\n            if part.name == 'statement':\n                items.extend(CatalogInterface._get_statement_sub_parts(part, 0))\n            else:\n                logger.warning(f'Control {control_id} has parts but first part name is {part.name} - not statement')\n        return items\n\n    def get_control_part_prose(self, control_id: str, part_name: str) -> str:\n\"\"\"\n        Get the prose for a named part in the control.\n\n        Args:\n            control_id: id of the control\n            part_name: name of the part\n\n        Returns:\n            Single string concatenating prose from all parts and sub-parts in control with that name.\n        \"\"\"\n        control = self.get_control(control_id)\n        return ControlInterface.get_part_prose(control, part_name)\n\n    def get_all_controls_from_catalog(self, recurse: bool) -> Iterator[cat.Control]:\n\"\"\"\n        Yield all controls from the actual catalog by group including optional sub controls.\n\n        Args:\n            recurse: Whether to recurse within controls, but groups are always recursed\n\n        Returns:\n            iterator of the controls in the catalog\n\n        Notes:\n            This follows the actual structure of the catalog and groups\n        \"\"\"\n        if self._catalog.groups:\n            for group in self._catalog.groups:\n                controls = self._get_all_controls_in_group(group, recurse)\n                for control in controls:\n                    yield control\n        if self._catalog.controls:\n            cat_controls = self._get_all_controls_in_list(self._catalog.controls, recurse)\n            for control in cat_controls:\n                yield control\n\n    def get_all_controls_from_dict(self) -> List[cat.Control]:\n\"\"\"Yield individual controls from the dict.\"\"\"\n        return [handle.control for handle in self._control_dict.values()]\n\n    def get_count_of_controls_in_dict(self) -> int:\n\"\"\"Find number of controls in the dict.\"\"\"\n        return len(self._control_dict.keys())\n\n    def get_count_of_controls_in_catalog(self, recurse: bool) -> int:\n\"\"\"Get count of controls from the actual catalog including optional sub controls.\"\"\"\n        return len(list(self.get_all_controls_from_catalog(recurse)))\n\n    def get_group_ids(self) -> List[str]:\n\"\"\"Get all the group id's as a list of sorted strings.\"\"\"\n        return sorted(filter(lambda id_: id_, list({control.group_id for control in self._control_dict.values()})))\n\n    def get_all_groups_from_catalog(self) -> List[cat.Group]:\n\"\"\"\n        Retrieve all groups in the catalog sorted by group_id.\n\n        This ignores controls that are direct children of the catalog.\n        \"\"\"\n        groups: List[cat.Group] = []\n        if self._catalog.groups:\n            for my_group in self._catalog.groups:\n                for res in CatalogInterface._get_groups_from_group(my_group):\n                    groups.append(res)\n        return sorted(groups, key=lambda group: group.id)\n\n    def get_statement_label_if_exists(self, control_id: str,\n                                      statement_id: str) -> Tuple[Optional[str], Optional[common.Part]]:\n\"\"\"Get statement label if available.\"\"\"\n\n        def does_part_exists(part: common.Part) -> bool:\n            does_match = False\n            if part.name and part.name in {const.STATEMENT, const.ITEM} and part.id == statement_id:\n                does_match = True\n            return does_match\n\n        control = self.get_control(control_id)\n        if not control:\n            return '', None\n        label = None\n        found_part = None\n        if control.parts:\n            for part in as_list(control.parts):\n                # Performance OSCAL assumption, ids are nested so recurse only if prefix\n                if part.id and statement_id.startswith(part.id):\n                    part = self.find_part_with_condition(part, does_part_exists)\n                    if part:\n                        label = ControlInterface.get_label(part)\n                        found_part = part\n                        break\n\n        return label, found_part\n\n    def find_part_with_condition(self, part: common.Part, condition: Callable) -> Optional[common.Part]:\n\"\"\"Traverse part and find subpart that satisfies given condition.\"\"\"\n        if condition(part):\n            # Part that satisfies the condition is found.\n            return part\n        else:\n            if part.parts:\n                for subpart in part.parts:\n                    found_part = self.find_part_with_condition(subpart, condition)\n                    if found_part:\n                        return found_part\n\n        return None\n\n    def delete_withdrawn_controls(self) -> None:\n\"\"\"Delete all withdrawn controls from the catalog.\"\"\"\n        delete_list = []\n        for control in self.get_all_controls_from_dict():\n            if ControlInterface.is_withdrawn(control):\n                delete_list.append(control.id)\n        for id_ in delete_list:\n            self.delete_control(id_)\n\n    @staticmethod\n    def _get_groups_from_group(group: cat.Group) -> Iterator[cat.Group]:\n        yield group\n        if group.groups:\n            for new_group in group.groups:\n                for res in CatalogInterface._get_groups_from_group(new_group):\n                    yield res\n\n    def get_group_info_by_control(self, control_id: str) -> Tuple[str, str, str]:\n\"\"\"Get the group_id, title, class for this control from the dict.\"\"\"\n        return (\n            '' if self._control_dict is None else self._control_dict[control_id].group_id,\n            '' if self._control_dict is None else self._control_dict[control_id].group_title,\n            '' if self._control_dict is None else self._control_dict[control_id].group_class\n        )\n\n    def get_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path into the markdown directory for this control based only on the groups.\"\"\"\n        return self._control_dict[control_id].group_path\n\n    def get_control_file_path(self, md_root: pathlib.Path, control_id: str) -> Optional[pathlib.Path]:\n\"\"\"Get the path to the control from the given root.\"\"\"\n        if control_id not in self._control_dict:\n            return None\n        path = md_root\n        for item in self.get_control_path(control_id):\n            path = path / item\n        return path / f'{control_id}.md'\n\n    def get_full_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path to the control including groups and sub-controls.\"\"\"\n        return self._control_dict[control_id].control_path\n\n    def replace_control(self, control: cat.Control) -> None:\n\"\"\"\n        Replace the control in the control_dict.\n\n        This only replaces the parent control and not its children.\n        \"\"\"\n        self._control_dict[control.id].control = control\n\n    def delete_control(self, control_id: str) -> None:\n\"\"\"\n        Delete the control from the control_dict based on id.\n\n        Delete all its dependent children also.\n        \"\"\"\n        control = self.get_control(control_id)\n        if control:\n            for sub_control_id in self.get_dependent_control_ids(control.id):\n                self._control_dict.pop(sub_control_id, None)\n            self._control_dict.pop(control_id, None)\n\n    def get_catalog(self, update=True) -> cat.Catalog:\n\"\"\"Safe method to get catalog after forced update from catalog dict.\"\"\"\n        if update:\n            self.update_catalog_controls()\n        return self._catalog\n\n    def _update_all_controls_in_list(self, controls: List[cat.Control]) -> List[cat.Control]:\n\"\"\"\n        Given a list of controls, create fresh list pulled from the control dict.\n\n        Args:\n            controls: a list of controls in the original catalog\n\n        Returns:\n            The new list of updated controls, possibly with some missing if they have been removed from the dict.\n            Children are inserted as needed into parent controls.\n        \"\"\"\n        new_list: List[cat.Control] = []\n        for control in controls:\n            # first update the control itself by getting it from the dict\n            new_control = self.get_control(control.id)\n            if new_control:\n                # this overrides any sub controls in the control itself\n                # any added sub-controls should add to the skipped list\n                new_control.controls = self._update_all_controls_in_list(as_list(control.controls))\n                new_control.controls = none_if_empty(new_control.controls)\n                new_list.append(new_control)\n        return new_list\n\n    def _update_all_controls_in_group(self, group: cat.Group) -> None:\n\"\"\"Given a group of controls, create fresh version pulled from the control dict.\"\"\"\n        group.controls = self._update_all_controls_in_list(as_list(group.controls))\n        group.controls = none_if_empty(group.controls)\n        new_groups: List[cat.Group] = []\n        for sub_group in as_list(group.groups):\n            self._update_all_controls_in_group(sub_group)\n            new_groups.append(sub_group)\n        group.groups = none_if_empty(new_groups)\n\n    def _insert_control_in_catalog(self, control_handle: ControlHandle) -> None:\n\"\"\"Insert the control into the catalog based on its path.\"\"\"\n        path = control_handle.group_path\n        node = self._catalog\n        if path[0] != '':\n            for group_id in path:\n                found_group = None\n                for group in as_list(node.groups):\n                    if group.id == group_id:\n                        found_group = group\n                        break\n                if found_group:\n                    node = found_group\n                else:\n                    raise TrestleError(f'No controls found in catalog for group {group.id}')\n            node.title = control_handle.group_title\n            node.class_ = control_handle.group_class\n        node.controls = delete_item_from_list(\n            as_list(node.controls), control_handle.control.id, lambda control: control.id\n        )\n        node.controls.append(control_handle.control)\n        node.controls = none_if_empty(sorted(node.controls, key=lambda control: ControlInterface.get_sort_id(control)))\n\n    def update_catalog_controls(self) -> None:\n\"\"\"\n        Update the actual catalog by pulling fresh controls from the dict.\n\n        During assembly, controls may be added, but not children of controls.\n        New groups may not be added.\n        A control containing controls cannot be added.  Controls containing controls are only available if\n        the parent catalog was loaded from json.\n        \"\"\"\n        # first go through the catalog and pull existing controls from the dict\n        for group in as_list(self._catalog.groups):\n            self._update_all_controls_in_group(group)\n\n        new_list = []\n        for control in as_list(self._catalog.controls):\n            new_control = self.get_control(control.id)\n            new_control.controls = self._update_all_controls_in_list(as_list(control.controls))\n            new_control.controls = none_if_empty(new_control.controls)\n            new_list.append(new_control)\n        self._catalog.controls = none_if_empty(new_list)\n\n        # now add any new controls that are discovered in the dict\n        ids_in_catalog = CatalogInterface.get_control_ids_from_catalog(self._catalog)\n        for control_handle in self._control_dict.values():\n            if control_handle.control.id not in ids_in_catalog:\n                self._insert_control_in_catalog(control_handle)\n\n        self._catalog.params = none_if_empty(list(self.loose_param_dict.values()))\n\n    def _find_string_in_part(self, control_id: str, part: common.Part, seek_str: str) -> List[str]:\n        hits: List[str] = []\n        if part.prose and part.prose.find(seek_str) >= 0:\n            hits.append((control_id, part.prose))\n        if part.parts:\n            for sub_part in part.parts:\n                hits.extend(self._find_string_in_part(control_id, sub_part, seek_str))\n        return hits\n\n    def find_string_in_control(self, control: cat.Control, seek_str: str) -> List[Tuple[str, str]]:\n\"\"\"Find all instances of this string in prose of control.\"\"\"\n        hits: List[Tuple[str, str]] = []\n        if control.parts:\n            for part in control.parts:\n                hits.extend(self._find_string_in_part(control.id, part, seek_str))\n        return hits\n\n    @staticmethod\n    def _get_full_profile_param_dict(profile: Optional[prof.Profile]) -> Dict[str, common.Parameter]:\n\"\"\"Get the full mapping of param_id to modified value for this profiles set_params.\"\"\"\n        set_param_dict: Dict[str, common.Parameter] = {}\n        if profile and profile.modify:\n            for set_param in as_list(profile.modify.set_parameters):\n                param = ControlInterface.setparam_to_param(set_param.param_id, set_param)\n                set_param_dict[set_param.param_id] = param\n        return set_param_dict\n\n    @staticmethod\n    def _get_profile_param_dict(\n        control: cat.Control, profile_param_dict: Dict[str, common.Parameter], values_only: bool\n    ) -> Dict[str, common.Parameter]:\n\"\"\"\n        Get the dict of params for this control including possible overrides made by the profile modifications.\n\n        Args:\n            control: The control being queried\n            profile_param_dict: The full dict of params and modified values made by the profile\n\n        Returns:\n            mapping of param ids to their final parameter states after possible modify by the profile setparameters\n        \"\"\"\n        # get the mapping of param_id's to params for this control, excluding those with no value set\n        param_dict = ControlInterface.get_control_param_dict(control, values_only)\n        for key in param_dict.keys():\n            if key in profile_param_dict:\n                param_dict[key] = profile_param_dict[key]\n        return param_dict\n\n    def _get_full_param_dict(self) -> Dict[str, common.Parameter]:\n        param_dict: Dict[str, common.Parameter] = {}\n        # build the full mapping of params to values from the catalog interface\n        for control in self.get_all_controls_from_dict():\n            param_dict.update(ControlInterface.get_control_param_dict(control, False))\n        return param_dict\n\n    def _change_prose_with_param_values(\n        self,\n        param_format,\n        param_rep,\n        show_value_warnings: bool,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Go through all controls and change prose based on param values.\"\"\"\n        param_dict = self._get_full_param_dict()\n        # insert param values into prose of all controls\n        for control in self.get_all_controls_from_dict():\n            ControlInterface.replace_control_prose(\n                control,\n                param_dict,\n                param_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n\n    @staticmethod\n    def _get_display_name_and_ns(param: common.Parameter) -> Tuple[Optional[str], Optional[str]]:\n        for prop in as_list(param.props):\n            if prop.name == const.DISPLAY_NAME:\n                ns = str(prop.ns) if prop.ns else None\n                return prop.value, ns\n        return None, None\n\n    @staticmethod\n    def _get_param_value_origin_and_ns(param: common.Parameter) -> Tuple[Optional[str], Optional[str]]:\n        for prop in as_list(param.props):\n            if prop.name == const.PARAM_VALUE_ORIGIN:\n                ns = str(prop.ns) if prop.ns else None\n                return prop.value, ns\n        return None, None\n\n    @staticmethod\n    def _prune_controls(md_path: pathlib.Path, written_controls: Set[str]) -> List[str]:\n\"\"\"Search directory and remove any controls that were not written out.\"\"\"\n        deleted_controls = []\n        for control_file in md_path.rglob('*.md'):\n            if control_file.stem not in written_controls:\n                logger.debug(\n                    f'Existing control markdown {control_file} deleted since it was not written out during generate'\n                )  # noqa E501\n                control_file.unlink()\n                deleted_controls.append(control_file.stem)\n        return sorted(deleted_controls)\n\n    def _extend_rules_param_list(\n        self, control_id: str, header: Dict[str, Any], param_id_rule_name_map: Dict[str, str]\n    ) -> None:\n\"\"\"Go through all set_params and put in rules param list if name matches.\"\"\"\n        control_comp_set_params = {}\n        rules_set_params = {}\n        all_set_params = self.get_control_comp_set_params(control_id)\n        for comp_name, param_list in all_set_params.items():\n            for param in param_list:\n                param_vals = none_if_empty(as_list(param.values))\n                rule_name = deep_get(param_id_rule_name_map, [comp_name, param.param_id], None)\n                if rule_name:\n                    param_dict = {'name': param.param_id}\n                    if param_vals:\n                        param_dict['values'] = param_vals\n                    deep_append(rules_set_params, [comp_name], param_dict)\n        set_or_pop(header, const.COMP_DEF_RULES_PARAM_VALS_TAG, rules_set_params)\n        set_or_pop(header, const.SET_PARAMS_TAG, control_comp_set_params)\n\n    def _get_control_memory_info(self, control_id: str, context: ControlContext) -> Tuple[Dict[str, Any], CompDict]:\n\"\"\"Build the rule info for the control into the header.\"\"\"\n        header = {}\n        rule_names_list: List[str] = []\n        comp_dict = self.get_comp_info(control_id)\n        # find the rule names that are needed by the control\n        for _, value in comp_dict.items():\n            for comp_info in value.values():\n                rule_names_list.extend(as_list(comp_info.rules))\n        if rule_names_list:\n            header_rules_dict = {}\n            rule_ids = {}\n            param_id_rule_name_map = {}\n            rule_id_rule_name_map = {}\n            # only include rules needed by control in the header\n            for comp_name, rules_dict in context.rules_dict.items():\n                for rule_id, rule_dict in rules_dict.items():\n                    if rule_dict['name'] in rule_names_list:\n                        deep_append(rule_ids, [comp_name], rule_id)\n                        deep_append(header_rules_dict, [comp_name], rule_dict)\n                        deep_set(rule_id_rule_name_map, [comp_name, rule_id], rule_dict['name'])\n            set_or_pop(header, const.COMP_DEF_RULES_TAG, header_rules_dict)\n            rules_params = {}\n            rules_param_names = []\n            for comp_name, rules_params_dict in as_dict(context.rules_params_dict).items():\n                for rule_id, rules_parameters in rules_params_dict.items():\n                    if rule_id in rule_ids.get(comp_name, []):\n                        for rule_parameter in rules_parameters:\n                            param_name = rule_parameter['name']\n                            rules_param_names.append(param_name)\n                            rule_parameter[const.HEADER_RULE_ID] = rule_id_rule_name_map[comp_name].get(rule_id, None)\n                            deep_append(rules_params, [comp_name], rule_parameter)\n                            deep_set(\n                                param_id_rule_name_map, [comp_name, rule_parameter['name']],\n                                rule_id_rule_name_map[comp_name][rule_id]\n                            )\n            set_or_pop(header, const.RULES_PARAMS_TAG, rules_params)\n\n            self._extend_rules_param_list(control_id, header, param_id_rule_name_map)\n\n        return header, comp_dict\n\n    @staticmethod\n    def _get_group_ids_and_dirs(md_path: pathlib.Path) -> Dict[str, pathlib.Path]:\n\"\"\"\n        Create a sorted map of group id to group dir that is ordered by group id.\n\n        This includes '' as the root group id.\n        \"\"\"\n        # manually insert the top dir as group ''\n        id_map: Dict[str, pathlib.Path] = {'': md_path}\n        for gdir in md_path.rglob('*'):\n            if gdir.is_dir():\n                dir_name = gdir.parts[-1]\n                id_map[dir_name] = gdir\n        # rebuild the dict by inserting items in manner sorted by key\n        sorted_id_map: Dict[str, pathlib.Path] = {}\n        for key in sorted(id_map):\n            sorted_id_map[key] = id_map[key]\n        return sorted_id_map\n\n    def get_sections(self) -> List[str]:\n\"\"\"Get the available sections by a full index of all controls.\"\"\"\n        return list(\n            {\n                part.name\n                for control_handle in self._control_dict.values()\n                for part in as_list(control_handle.control.parts)\n                if part.name != const.STATEMENT\n            }\n        )\n\n    def _find_control_in_group(self, group_id: str) -> Tuple[str, ControlHandle]:\n\"\"\"\n        Find a representative control for this group and its control handle.\n\n        This is a simple way to get group info (title etc.) given only group id.\n        It is not intended for high performance loops.  Use only as needed.\n        \"\"\"\n        for control_id, control_handle in self._control_dict.items():\n            if control_handle.group_id == group_id:\n                return control_id, control_handle\n        raise TrestleError(f'No controls found for group {group_id}')\n\n    def _add_control_imp_comp_info(\n        self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]], comp_rules_props: List[common.Property]\n    ) -> None:\n\"\"\"Add component info to the impreqs of the control implementation based on applied rules.\"\"\"\n        control_imp_rules_dict, control_imp_rules_params_dict, ci_rules_props = ControlInterface.get_rules_and_params_dict_from_item(context.control_implementation)  # noqa E501\n        context.rules_dict[context.comp_name].update(control_imp_rules_dict)\n        comp_rules_params_dict = context.rules_params_dict.get(context.comp_name, {})\n        comp_rules_params_dict.update(control_imp_rules_params_dict)\n        context.rules_params_dict[context.comp_name] = comp_rules_params_dict\n        ci_set_params = ControlInterface.get_set_params_from_item(context.control_implementation)\n        catalog_control_ids = self.get_control_ids()\n        for imp_req in as_list(context.control_implementation.implemented_requirements):\n            if imp_req.control_id not in catalog_control_ids:\n                logger.warning(\n                    f'Component {context.component.title} references control {imp_req.control_id} not in profile.'\n                )\n            control_part_id_map = part_id_map.get(imp_req.control_id, {})\n            # find if any rules apply to this control, including in statements\n            control_rules, statement_rules, ir_props = ControlInterface.get_rule_list_for_imp_req(imp_req)\n            rule_props = comp_rules_props[:]\n            rule_props.extend(ci_rules_props)\n            rule_props.extend(ir_props)\n            rule_props = ControlInterface.clean_props(rule_props, remove_imp_status=False)\n            if control_rules:\n                status = ControlInterface.get_status_from_props(imp_req)\n                final_props = ControlInterface.cull_props_by_rules(rule_props, control_rules)\n                comp_info = ComponentImpInfo(imp_req.description, control_rules, final_props, status)\n                self.add_comp_info(imp_req.control_id, context.comp_name, '', comp_info)\n            set_params = copy.deepcopy(ci_set_params)\n            set_params.update(ControlInterface.get_set_params_from_item(imp_req))\n            for set_param in set_params.values():\n                # add to control_comp_set_params dict\n                self.add_comp_set_param(imp_req.control_id, context.comp_name, set_param)\n            for statement in as_list(imp_req.statements):\n                rule_list, stat_props = ControlInterface.get_rule_list_for_item(statement)\n                if rule_list:\n                    status = ControlInterface.get_status_from_props(statement)\n                    if statement.statement_id not in control_part_id_map:\n                        label = statement.statement_id\n                        logger.warning(\n                            f'No statement label found for statement id {label}.  Defaulting to {label}.'  # noqa E501\n                        )\n                    else:\n                        label = control_part_id_map[statement.statement_id]\n                    all_props = rule_props[:]\n                    all_props.extend(stat_props)\n                    final_props = ControlInterface.cull_props_by_rules(all_props, rule_list)\n                    comp_info = ComponentImpInfo(statement.description, rule_list, final_props, status)\n                    self.add_comp_info(imp_req.control_id, context.comp_name, label, comp_info)\n\n    def generate_control_rule_info(self, part_id_map: Dict[str, Dict[str, str]], context: ControlContext) -> None:\n\"\"\"\n        Generate rule info for controls directly from the components.\n\n        Args:\n            part_id_map: Mapping of label to part in the control\n            context: Control context for the current operation\n\n        Returns:\n            Returns nothing but places the rules_dict and rules_params_dict in the context for each component\n        \"\"\"\n        context.rules_dict = {}\n        context.rules_params_dict = {}\n        comps_uuids = []\n        for comp_def_name in context.comp_def_name_list:\n            context.comp_def, _ = ModelUtils.load_model_for_class(\n                context.trestle_root,\n                comp_def_name,\n                comp.ComponentDefinition\n            )\n            component_uuids = [comp.uuid for comp in context.comp_def.components]\n            comps_uuids.extend(component_uuids)\n            for component in as_list(context.comp_def.components):\n                context.component = component\n                context.comp_name = component.title\n                # get top level rule info applying to all controls from the component props\n                comp_rules_dict, comp_rules_params_dict, comp_rules_props = ControlInterface.get_rules_and_params_dict_from_item(component)  # noqa E501\n                context.rules_dict[context.comp_name] = comp_rules_dict\n                deep_update(context.rules_params_dict, [context.comp_name], comp_rules_params_dict)\n                for control_imp in as_list(component.control_implementations):\n                    context.control_implementation = control_imp\n                    self._add_control_imp_comp_info(context, part_id_map, comp_rules_props)\n                # add the rule_id to the param_dict\n                for param_comp_name, rule_param_dict in context.rules_params_dict.items():\n                    for rule_tag, params_list in rule_param_dict.items():\n                        for param in params_list:\n                            rule_dict = deep_get(context.rules_dict, [param_comp_name, rule_tag], {})\n                            param[const.HEADER_RULE_ID] = rule_dict.get(const.NAME, 'unknown_rule')\n        # determine if there are duplicated uuids and throw an exception\n        dup_comp_uuids = set({comp_uuid for comp_uuid in comps_uuids if comps_uuids.count(comp_uuid) > 1})\n        if len(dup_comp_uuids) > 0:\n            # throw an exception if there are repeated component uuids\n            for comp_uuid in dup_comp_uuids:\n                logger.error(f'Component uuid { comp_uuid } is duplicated')\n            raise TrestleError('Component uuids cannot be duplicated between different component definitions')\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.ControlHandle","title":" ControlHandle dataclass","text":"

                                    Convenience class for handling controls as members of a group.

                                    group_id: id of parent group or '' if not in a group group_title: title of the group group_class: class of the group path: path of parent groups leading to this control - without the final control_id, or [''] if in cat list important to remember that controls may not be in a group and are directly attached to cat control: the control itself

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    @dataclass\nclass ControlHandle:\n\"\"\"Convenience class for handling controls as members of a group.\n\n    group_id: id of parent group or '' if not in a group\n    group_title: title of the group\n    group_class: class of the group\n    path: path of parent groups leading to this control - without the final control_id, or [''] if in cat list\n    important to remember that controls may not be in a group and are directly attached to cat\n    control: the control itself\n    \"\"\"\n\n    group_id: str\n    group_title: Optional[str]\n    group_class: Optional[str]\n    group_path: List[str]\n    control_path: List[str]\n    control: cat.Control\n
                                    control: Control dataclass-field \u00a4 control_path: List[str] dataclass-field \u00a4 group_class: Optional[str] dataclass-field \u00a4 group_id: str dataclass-field \u00a4 group_path: List[str] dataclass-field \u00a4 group_title: Optional[str] dataclass-field \u00a4 __eq__(self, other) special \u00a4 __init__(self, group_id, group_title, group_class, group_path, control_path, control) special \u00a4 __repr__(self) special \u00a4"},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.__init__","title":"__init__(self, catalog=None) special","text":"

                                    Initialize the interface with the catalog.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def __init__(self, catalog: Optional[cat.Catalog] = None) -> None:\n\"\"\"Initialize the interface with the catalog.\"\"\"\n    self._catalog = catalog\n    self._param_control_map: Dict[str, str] = {}\n    self._generate_group_index: int = 0\n    self._control_dict = self._create_control_dict() if catalog else None\n    self.loose_param_dict: Dict[str, common.Parameter] = {param.id: param\n                                                          for param in as_list(catalog.params)} if catalog else {}\n    # map control id to CompDict\n    self._control_comp_dicts: Dict[str, CompDict] = {}\n    # map control id to dict containing set parameters by component\n    self._control_comp_set_params: Dict[str, Dict[str, comp.SetParameter]] = {}\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.add_comp_info","title":"add_comp_info(self, control_id, comp_name, label, comp_info)","text":"

                                    Add comp_info for a control.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def add_comp_info(self, control_id: str, comp_name: str, label: str, comp_info: ComponentImpInfo) -> None:\n\"\"\"Add comp_info for a control.\"\"\"\n    deep_set(self._control_comp_dicts, [control_id, comp_name, label], comp_info)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.add_comp_set_param","title":"add_comp_set_param(self, control_id, comp_name, set_param)","text":"

                                    Add component setparam for control with overwrite.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def add_comp_set_param(self, control_id: str, comp_name: str, set_param: comp.SetParameter) -> None:\n\"\"\"Add component setparam for control with overwrite.\"\"\"\n    deep_append(self._control_comp_set_params, [control_id, comp_name], set_param)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.clear_comp_dicts","title":"clear_comp_dicts(self)","text":"

                                    Clear the control component dicts.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def clear_comp_dicts(self) -> None:\n\"\"\"Clear the control component dicts.\"\"\"\n    self._control_comp_dicts = {}\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.clear_set_params","title":"clear_set_params(self)","text":"

                                    Clear the control set params.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def clear_set_params(self) -> None:\n\"\"\"Clear the control set params.\"\"\"\n    self._control_comp_set_params = {}\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.delete_control","title":"delete_control(self, control_id)","text":"

                                    Delete the control from the control_dict based on id.

                                    Delete all its dependent children also.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def delete_control(self, control_id: str) -> None:\n\"\"\"\n    Delete the control from the control_dict based on id.\n\n    Delete all its dependent children also.\n    \"\"\"\n    control = self.get_control(control_id)\n    if control:\n        for sub_control_id in self.get_dependent_control_ids(control.id):\n            self._control_dict.pop(sub_control_id, None)\n        self._control_dict.pop(control_id, None)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.delete_withdrawn_controls","title":"delete_withdrawn_controls(self)","text":"

                                    Delete all withdrawn controls from the catalog.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def delete_withdrawn_controls(self) -> None:\n\"\"\"Delete all withdrawn controls from the catalog.\"\"\"\n    delete_list = []\n    for control in self.get_all_controls_from_dict():\n        if ControlInterface.is_withdrawn(control):\n            delete_list.append(control.id)\n    for id_ in delete_list:\n        self.delete_control(id_)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.find_part_with_condition","title":"find_part_with_condition(self, part, condition)","text":"

                                    Traverse part and find subpart that satisfies given condition.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def find_part_with_condition(self, part: common.Part, condition: Callable) -> Optional[common.Part]:\n\"\"\"Traverse part and find subpart that satisfies given condition.\"\"\"\n    if condition(part):\n        # Part that satisfies the condition is found.\n        return part\n    else:\n        if part.parts:\n            for subpart in part.parts:\n                found_part = self.find_part_with_condition(subpart, condition)\n                if found_part:\n                    return found_part\n\n    return None\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.find_string_in_control","title":"find_string_in_control(self, control, seek_str)","text":"

                                    Find all instances of this string in prose of control.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def find_string_in_control(self, control: cat.Control, seek_str: str) -> List[Tuple[str, str]]:\n\"\"\"Find all instances of this string in prose of control.\"\"\"\n    hits: List[Tuple[str, str]] = []\n    if control.parts:\n        for part in control.parts:\n            hits.extend(self._find_string_in_part(control.id, part, seek_str))\n    return hits\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.generate_control_rule_info","title":"generate_control_rule_info(self, part_id_map, context)","text":"

                                    Generate rule info for controls directly from the components.

                                    Parameters:

                                    Name Type Description Default part_id_map Dict[str, Dict[str, str]]

                                    Mapping of label to part in the control

                                    required context ControlContext

                                    Control context for the current operation

                                    required

                                    Returns:

                                    Type Description None

                                    Returns nothing but places the rules_dict and rules_params_dict in the context for each component

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def generate_control_rule_info(self, part_id_map: Dict[str, Dict[str, str]], context: ControlContext) -> None:\n\"\"\"\n    Generate rule info for controls directly from the components.\n\n    Args:\n        part_id_map: Mapping of label to part in the control\n        context: Control context for the current operation\n\n    Returns:\n        Returns nothing but places the rules_dict and rules_params_dict in the context for each component\n    \"\"\"\n    context.rules_dict = {}\n    context.rules_params_dict = {}\n    comps_uuids = []\n    for comp_def_name in context.comp_def_name_list:\n        context.comp_def, _ = ModelUtils.load_model_for_class(\n            context.trestle_root,\n            comp_def_name,\n            comp.ComponentDefinition\n        )\n        component_uuids = [comp.uuid for comp in context.comp_def.components]\n        comps_uuids.extend(component_uuids)\n        for component in as_list(context.comp_def.components):\n            context.component = component\n            context.comp_name = component.title\n            # get top level rule info applying to all controls from the component props\n            comp_rules_dict, comp_rules_params_dict, comp_rules_props = ControlInterface.get_rules_and_params_dict_from_item(component)  # noqa E501\n            context.rules_dict[context.comp_name] = comp_rules_dict\n            deep_update(context.rules_params_dict, [context.comp_name], comp_rules_params_dict)\n            for control_imp in as_list(component.control_implementations):\n                context.control_implementation = control_imp\n                self._add_control_imp_comp_info(context, part_id_map, comp_rules_props)\n            # add the rule_id to the param_dict\n            for param_comp_name, rule_param_dict in context.rules_params_dict.items():\n                for rule_tag, params_list in rule_param_dict.items():\n                    for param in params_list:\n                        rule_dict = deep_get(context.rules_dict, [param_comp_name, rule_tag], {})\n                        param[const.HEADER_RULE_ID] = rule_dict.get(const.NAME, 'unknown_rule')\n    # determine if there are duplicated uuids and throw an exception\n    dup_comp_uuids = set({comp_uuid for comp_uuid in comps_uuids if comps_uuids.count(comp_uuid) > 1})\n    if len(dup_comp_uuids) > 0:\n        # throw an exception if there are repeated component uuids\n        for comp_uuid in dup_comp_uuids:\n            logger.error(f'Component uuid { comp_uuid } is duplicated')\n        raise TrestleError('Component uuids cannot be duplicated between different component definitions')\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_all_controls_from_catalog","title":"get_all_controls_from_catalog(self, recurse)","text":"

                                    Yield all controls from the actual catalog by group including optional sub controls.

                                    Parameters:

                                    Name Type Description Default recurse bool

                                    Whether to recurse within controls, but groups are always recursed

                                    required

                                    Returns:

                                    Type Description Iterator[trestle.oscal.catalog.Control]

                                    iterator of the controls in the catalog

                                    Notes

                                    This follows the actual structure of the catalog and groups

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_all_controls_from_catalog(self, recurse: bool) -> Iterator[cat.Control]:\n\"\"\"\n    Yield all controls from the actual catalog by group including optional sub controls.\n\n    Args:\n        recurse: Whether to recurse within controls, but groups are always recursed\n\n    Returns:\n        iterator of the controls in the catalog\n\n    Notes:\n        This follows the actual structure of the catalog and groups\n    \"\"\"\n    if self._catalog.groups:\n        for group in self._catalog.groups:\n            controls = self._get_all_controls_in_group(group, recurse)\n            for control in controls:\n                yield control\n    if self._catalog.controls:\n        cat_controls = self._get_all_controls_in_list(self._catalog.controls, recurse)\n        for control in cat_controls:\n            yield control\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_all_controls_from_dict","title":"get_all_controls_from_dict(self)","text":"

                                    Yield individual controls from the dict.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_all_controls_from_dict(self) -> List[cat.Control]:\n\"\"\"Yield individual controls from the dict.\"\"\"\n    return [handle.control for handle in self._control_dict.values()]\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_all_groups_from_catalog","title":"get_all_groups_from_catalog(self)","text":"

                                    Retrieve all groups in the catalog sorted by group_id.

                                    This ignores controls that are direct children of the catalog.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_all_groups_from_catalog(self) -> List[cat.Group]:\n\"\"\"\n    Retrieve all groups in the catalog sorted by group_id.\n\n    This ignores controls that are direct children of the catalog.\n    \"\"\"\n    groups: List[cat.Group] = []\n    if self._catalog.groups:\n        for my_group in self._catalog.groups:\n            for res in CatalogInterface._get_groups_from_group(my_group):\n                groups.append(res)\n    return sorted(groups, key=lambda group: group.id)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_catalog","title":"get_catalog(self, update=True)","text":"

                                    Safe method to get catalog after forced update from catalog dict.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_catalog(self, update=True) -> cat.Catalog:\n\"\"\"Safe method to get catalog after forced update from catalog dict.\"\"\"\n    if update:\n        self.update_catalog_controls()\n    return self._catalog\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_catalog_title","title":"get_catalog_title(self)","text":"

                                    Get the title of the catalog.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_catalog_title(self) -> str:\n\"\"\"Get the title of the catalog.\"\"\"\n    return self._catalog.metadata.title\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_comp_info","title":"get_comp_info(self, control_id)","text":"

                                    Get comp_dict for this control.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_comp_info(self, control_id: str) -> CompDict:\n\"\"\"Get comp_dict for this control.\"\"\"\n    return self._control_comp_dicts.get(control_id, {})\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control","title":"get_control(self, control_id)","text":"

                                    Get control from the control dict with this id.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control(self, control_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from the control dict with this id.\"\"\"\n    return None if control_id not in self._control_dict else self._control_dict[control_id].control\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_by_param_id","title":"get_control_by_param_id(self, param_id)","text":"

                                    Get control from catalog that has this param id using the dict.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control_by_param_id(self, param_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from catalog that has this param id using the dict.\"\"\"\n    if param_id in self._param_control_map:\n        return self.get_control(self._param_control_map[param_id])\n    return None\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_comp_set_params","title":"get_control_comp_set_params(self, control_id)","text":"

                                    Get dict of setparams list per component.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control_comp_set_params(self, control_id: str) -> Dict[str, List[comp.SetParameter]]:\n\"\"\"Get dict of setparams list per component.\"\"\"\n    return self._control_comp_set_params.get(control_id, {})\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_file_path","title":"get_control_file_path(self, md_root, control_id)","text":"

                                    Get the path to the control from the given root.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control_file_path(self, md_root: pathlib.Path, control_id: str) -> Optional[pathlib.Path]:\n\"\"\"Get the path to the control from the given root.\"\"\"\n    if control_id not in self._control_dict:\n        return None\n    path = md_root\n    for item in self.get_control_path(control_id):\n        path = path / item\n    return path / f'{control_id}.md'\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_id_and_status","title":"get_control_id_and_status(self, control_name)","text":"

                                    Get the control id and status using the control name.

                                    Returns empty string if status not found.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control_id_and_status(self, control_name: str) -> Tuple[str, str]:\n\"\"\"\n    Get the control id and status using the control name.\n\n    Returns empty string if status not found.\n    \"\"\"\n    for control in self.get_all_controls_from_dict():\n        if ControlInterface.get_label(control).strip().lower() == control_name.strip().lower():\n            status = ControlInterface.get_prop(control, 'status')\n            return control.id, status\n    return '', ''\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_ids","title":"get_control_ids(self)","text":"

                                    Get all control ids from the control dict.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control_ids(self) -> List[str]:\n\"\"\"Get all control ids from the control dict.\"\"\"\n    return self._control_dict.keys()\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_ids_from_catalog","title":"get_control_ids_from_catalog(catalog) staticmethod","text":"

                                    Get all control ids from a catalog.

                                    This is intended to provide a quick list of all controls in a catalog without the expense of building the control dict. So, if repeated queries are made into a catalog, it is worth instantiating a CatalogInterface and associated control dict. Otherwise just use this to get a list of all controls.

                                    This function is needed within the CatalogInterface in order to determine if new controls have been added to the dict and need to be inserted in the actual catalog during update.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    @staticmethod\ndef get_control_ids_from_catalog(catalog: cat.Catalog) -> List[str]:\n\"\"\"\n    Get all control ids from a catalog.\n\n    This is intended to provide a quick list of all controls in a catalog without the expense of building the\n    control dict.  So, if repeated queries are made into a catalog, it is worth instantiating a CatalogInterface\n    and associated control dict.  Otherwise just use this to get a list of all controls.\n\n    This function is needed within the CatalogInterface in order to determine if new controls have been added\n    to the dict and need to be inserted in the actual catalog during update.\n    \"\"\"\n    controls = CatalogInterface._get_all_controls_in_list(as_list(catalog.controls), True)\n    id_list = [control.id for control in controls]\n    for group in as_list(catalog.groups):\n        controls = CatalogInterface._get_all_controls_in_group(group, True)\n        id_list.extend([control.id for control in as_list(controls)])\n    return id_list\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_part_prose","title":"get_control_part_prose(self, control_id, part_name)","text":"

                                    Get the prose for a named part in the control.

                                    Parameters:

                                    Name Type Description Default control_id str

                                    id of the control

                                    required part_name str

                                    name of the part

                                    required

                                    Returns:

                                    Type Description str

                                    Single string concatenating prose from all parts and sub-parts in control with that name.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control_part_prose(self, control_id: str, part_name: str) -> str:\n\"\"\"\n    Get the prose for a named part in the control.\n\n    Args:\n        control_id: id of the control\n        part_name: name of the part\n\n    Returns:\n        Single string concatenating prose from all parts and sub-parts in control with that name.\n    \"\"\"\n    control = self.get_control(control_id)\n    return ControlInterface.get_part_prose(control, part_name)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_path","title":"get_control_path(self, control_id)","text":"

                                    Return the path into the markdown directory for this control based only on the groups.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path into the markdown directory for this control based only on the groups.\"\"\"\n    return self._control_dict[control_id].group_path\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_count_of_controls_in_catalog","title":"get_count_of_controls_in_catalog(self, recurse)","text":"

                                    Get count of controls from the actual catalog including optional sub controls.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_count_of_controls_in_catalog(self, recurse: bool) -> int:\n\"\"\"Get count of controls from the actual catalog including optional sub controls.\"\"\"\n    return len(list(self.get_all_controls_from_catalog(recurse)))\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_count_of_controls_in_dict","title":"get_count_of_controls_in_dict(self)","text":"

                                    Find number of controls in the dict.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_count_of_controls_in_dict(self) -> int:\n\"\"\"Find number of controls in the dict.\"\"\"\n    return len(self._control_dict.keys())\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_dependent_control_ids","title":"get_dependent_control_ids(self, control_id)","text":"

                                    Find all child ids of this control from the dict with recursion.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_dependent_control_ids(self, control_id: str) -> List[str]:\n\"\"\"Find all child ids of this control from the dict with recursion.\"\"\"\n    children: List[str] = []\n    control = self.get_control(control_id)\n    if control:\n        new_controls = self._get_all_controls_in_list(as_list(control.controls), True)\n        children.extend([con.id for con in new_controls])\n    return children\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_full_control_path","title":"get_full_control_path(self, control_id)","text":"

                                    Return the path to the control including groups and sub-controls.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_full_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path to the control including groups and sub-controls.\"\"\"\n    return self._control_dict[control_id].control_path\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_group_ids","title":"get_group_ids(self)","text":"

                                    Get all the group id's as a list of sorted strings.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_group_ids(self) -> List[str]:\n\"\"\"Get all the group id's as a list of sorted strings.\"\"\"\n    return sorted(filter(lambda id_: id_, list({control.group_id for control in self._control_dict.values()})))\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_group_info_by_control","title":"get_group_info_by_control(self, control_id)","text":"

                                    Get the group_id, title, class for this control from the dict.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_group_info_by_control(self, control_id: str) -> Tuple[str, str, str]:\n\"\"\"Get the group_id, title, class for this control from the dict.\"\"\"\n    return (\n        '' if self._control_dict is None else self._control_dict[control_id].group_id,\n        '' if self._control_dict is None else self._control_dict[control_id].group_title,\n        '' if self._control_dict is None else self._control_dict[control_id].group_class\n    )\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_sections","title":"get_sections(self)","text":"

                                    Get the available sections by a full index of all controls.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_sections(self) -> List[str]:\n\"\"\"Get the available sections by a full index of all controls.\"\"\"\n    return list(\n        {\n            part.name\n            for control_handle in self._control_dict.values()\n            for part in as_list(control_handle.control.parts)\n            if part.name != const.STATEMENT\n        }\n    )\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_sorted_controls_in_group","title":"get_sorted_controls_in_group(self, group_id)","text":"

                                    Get the list of controls in a group sorted by the control sort-id.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_sorted_controls_in_group(self, group_id: str) -> List[cat.Control]:\n\"\"\"Get the list of controls in a group sorted by the control sort-id.\"\"\"\n    controls: List[cat.Control] = []\n    for control in self.get_all_controls_from_dict():\n        grp_id, _, _ = self.get_group_info_by_control(control.id)\n        if grp_id == group_id:\n            controls.append(control)\n    return sorted(controls, key=lambda control: ControlInterface.get_sort_id(control))\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_statement_label_if_exists","title":"get_statement_label_if_exists(self, control_id, statement_id)","text":"

                                    Get statement label if available.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_statement_label_if_exists(self, control_id: str,\n                                  statement_id: str) -> Tuple[Optional[str], Optional[common.Part]]:\n\"\"\"Get statement label if available.\"\"\"\n\n    def does_part_exists(part: common.Part) -> bool:\n        does_match = False\n        if part.name and part.name in {const.STATEMENT, const.ITEM} and part.id == statement_id:\n            does_match = True\n        return does_match\n\n    control = self.get_control(control_id)\n    if not control:\n        return '', None\n    label = None\n    found_part = None\n    if control.parts:\n        for part in as_list(control.parts):\n            # Performance OSCAL assumption, ids are nested so recurse only if prefix\n            if part.id and statement_id.startswith(part.id):\n                part = self.find_part_with_condition(part, does_part_exists)\n                if part:\n                    label = ControlInterface.get_label(part)\n                    found_part = part\n                    break\n\n    return label, found_part\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_statement_part_id_map","title":"get_statement_part_id_map(self, label_as_key)","text":"

                                    Create mapping of label to part_id for top level parts in statement of all controls.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_statement_part_id_map(self, label_as_key: bool) -> Dict[str, Dict[str, str]]:\n\"\"\"Create mapping of label to part_id for top level parts in statement of all controls.\"\"\"\n    id_map = {}\n    for control in self.get_all_controls_from_catalog(True):\n        statement_part = get_item_from_list(control.parts, const.STATEMENT, lambda p: p.name)\n        if not statement_part:\n            continue\n        id_dict: Dict[str, str] = {}\n        for sub_part in as_list(statement_part.parts):\n            label = ControlInterface.get_label(sub_part)\n            # skip add to map for empty label\n            if not label:\n                continue\n            if label_as_key:\n                id_dict[label] = sub_part.id\n            else:\n                id_dict[sub_part.id] = label\n        if id_dict:\n            id_map[control.id] = id_dict\n    return id_map\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_statement_parts","title":"get_statement_parts(self, control_id)","text":"

                                    Get list of statement parts as dicts with indentation, label and prose.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def get_statement_parts(self, control_id: str) -> List[Dict[str, str]]:\n\"\"\"Get list of statement parts as dicts with indentation, label and prose.\"\"\"\n    items = []\n    control = self.get_control(control_id)\n\n    # control may have no statement or parts\n    # but if statement present it is first part\n    if control is None:\n        logger.warning(f'No control found for id {control_id}')\n    elif control.parts:\n        part = control.parts[0]\n        if part.name == 'statement':\n            items.extend(CatalogInterface._get_statement_sub_parts(part, 0))\n        else:\n            logger.warning(f'Control {control_id} has parts but first part name is {part.name} - not statement')\n    return items\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.replace_control","title":"replace_control(self, control)","text":"

                                    Replace the control in the control_dict.

                                    This only replaces the parent control and not its children.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def replace_control(self, control: cat.Control) -> None:\n\"\"\"\n    Replace the control in the control_dict.\n\n    This only replaces the parent control and not its children.\n    \"\"\"\n    self._control_dict[control.id].control = control\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.update_catalog_controls","title":"update_catalog_controls(self)","text":"

                                    Update the actual catalog by pulling fresh controls from the dict.

                                    During assembly, controls may be added, but not children of controls. New groups may not be added. A control containing controls cannot be added. Controls containing controls are only available if the parent catalog was loaded from json.

                                    Source code in trestle/core/catalog/catalog_interface.py
                                    def update_catalog_controls(self) -> None:\n\"\"\"\n    Update the actual catalog by pulling fresh controls from the dict.\n\n    During assembly, controls may be added, but not children of controls.\n    New groups may not be added.\n    A control containing controls cannot be added.  Controls containing controls are only available if\n    the parent catalog was loaded from json.\n    \"\"\"\n    # first go through the catalog and pull existing controls from the dict\n    for group in as_list(self._catalog.groups):\n        self._update_all_controls_in_group(group)\n\n    new_list = []\n    for control in as_list(self._catalog.controls):\n        new_control = self.get_control(control.id)\n        new_control.controls = self._update_all_controls_in_list(as_list(control.controls))\n        new_control.controls = none_if_empty(new_control.controls)\n        new_list.append(new_control)\n    self._catalog.controls = none_if_empty(new_list)\n\n    # now add any new controls that are discovered in the dict\n    ids_in_catalog = CatalogInterface.get_control_ids_from_catalog(self._catalog)\n    for control_handle in self._control_dict.values():\n        if control_handle.control.id not in ids_in_catalog:\n            self._insert_control_in_catalog(control_handle)\n\n    self._catalog.params = none_if_empty(list(self.loose_param_dict.values()))\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_merger/","title":"catalog_merger","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger","title":"trestle.core.catalog.catalog_merger","text":"

                                    Provide interface to merge one catalog to another.

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger","title":" CatalogMerger ","text":"

                                    Catalog merger.

                                    Catalog merger handles all operations related to merging contents of one catalog to another.

                                    Source code in trestle/core/catalog/catalog_merger.py
                                    class CatalogMerger():\n\"\"\"\n    Catalog merger.\n\n    Catalog merger handles all operations related to\n    merging contents of one catalog to another.\n    \"\"\"\n\n    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog merger.\"\"\"\n        self._catalog_interface = catalog_interface\n\n    @staticmethod\n    def merge_controls(dest: cat.Control, src: cat.Control, replace_params: bool) -> None:\n\"\"\"\n        Merge the src control into dest.\n\n        Args:\n            dest: destination control into which content will be added\n            src: source control with new content\n            replace_params: replace the control params with the new ones\n        \"\"\"\n        ControlInterface.merge_parts(dest, src)\n        if replace_params:\n            dest.params = src.params\n\n    def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"\n        Merge the provided new catalog controls into the original catalog in this catalog interface.\n\n        Args:\n            catalog: catalog containing controls that are merged into the current catalog of the interface\n            replace_params: replace all params in the control with the new ones\n\n        Notes:\n            This is mainly to support the reading of a catalog from markdown.  It allows retention of content such as\n            metadata and backmatter, along with labels and other parameter attributes that aren't in markdown.\n            The list of controls and group structure is specified by the markdown structure - but this doesn't allow\n            controls to contain controls.  Group lists are specified per directory.\n\n            Reading the markdown tells you groups and controls in them - and groups in groups.\n            Controls cannot change groups.  If the control was in the original json, its parts are replaced,\n            including its parameters.  Only values may be specified.  If no value specified, the value is unset in json.\n        \"\"\"\n        cat_interface = CatalogInterface(catalog)\n        for src in cat_interface.get_all_controls_from_dict():\n            group_id, _, _ = cat_interface.get_group_info_by_control(src.id)\n            dest = self._catalog_interface.get_control(src.id)\n            if dest:\n                dest_group, _, _ = self._catalog_interface.get_group_info_by_control(dest.id)\n                if dest_group != group_id:\n                    raise TrestleError(f'Markdown for control {src.id} has different group id.')\n                CatalogMerger.merge_controls(dest, src, replace_params)\n                self._catalog_interface.replace_control(dest)\n            else:\n                # this is a new control that isn't already in the merge destination\n                # need to add the control knowing its group must already exist\n                # get group info from an arbitrary control already present in group\n                _, control_handle = self._catalog_interface._find_control_in_group(group_id)\n                new_control_handle = copy.deepcopy(control_handle)\n                new_control_handle.control = src\n                # add the control and its handle to the param_dict\n                self._catalog_interface._control_dict[src.id] = new_control_handle  # type: ignore\n\n        # now need to cull any controls that are not in the src catalog\n        if cat_interface._control_dict is None:\n            handled_ids = None\n        else:\n            handled_ids = set(cat_interface._control_dict.keys())\n        orig_ids = set(self._catalog_interface._control_dict.keys())\n        extra_ids = orig_ids.difference(handled_ids)\n        for extra_id in sorted(extra_ids):\n            self._catalog_interface._control_dict.pop(extra_id)\n\n        self._catalog_interface.update_catalog_controls()\n\n    def _merge_header_and_comp_dict(\n        self, control: cat.Control, control_file_path: pathlib.Path, context: ControlContext\n    ) -> None:\n\"\"\"\n        Merge the header and the comp_dict.\n\n        Notes:\n            now have all rules in context.rules_dict and all rules_params in context.rules_params_dict\n            all set-params per component for each control are in the cat interface\n            all comp-infos by control and part are in the cat interface\n\n            can now write out catalog and pull from the markdown:\n            header for param values to set during assem\n            prose and status for This System\n            status for all parts that still have rules\n        \"\"\"\n        memory_header, memory_comp_dict = self._catalog_interface._get_control_memory_info(control.id, context)\n        ControlInterface.merge_dicts_deep(memory_header, context.merged_header, True)\n        md_header, md_comp_dict = CatalogReader._read_comp_info_from_md(control_file_path, context)\n        # md content replaces memory content but unless memory has no rules for it and the content is removed\n        # but This System doesn't require rules, so its content is always kept\n\n        # go through the just-read md_comp_dict and update the memory dict with contents in md\n        if const.SSP_MAIN_COMP_NAME in md_comp_dict:\n            memory_comp_dict[const.SSP_MAIN_COMP_NAME] = md_comp_dict[const.SSP_MAIN_COMP_NAME]\n        for comp_name, md_label_dict in md_comp_dict.items():\n            memory_label_dict = memory_comp_dict.get(comp_name, None)\n            if comp_name != const.SSP_MAIN_COMP_NAME:\n                if not memory_label_dict:\n                    continue\n                for label, comp_info in md_label_dict.items():\n                    if label in memory_label_dict:\n                        memory_label_dict[label] = comp_info\n\n        memory_rules_param_vals = memory_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {})\n        md_rules_param_vals = md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {})\n        for comp_name, val_list in md_rules_param_vals.items():\n            val_dict = {val['name']: val for val in val_list}\n            if comp_name not in memory_rules_param_vals:\n                memory_rules_param_vals[comp_name] = val_list\n            else:\n                # merge the lists with priority to md\n                new_list = []\n                mem_list = memory_rules_param_vals[comp_name]\n                mem_names = [mem['name'] for mem in mem_list]\n                for val in mem_list:\n                    new_list.append(val_dict.get(val['name'], val))\n                for key, val in val_dict.items():\n                    if key not in mem_names:\n                        new_list.append(val)\n                memory_rules_param_vals[comp_name] = new_list\n\n        set_or_pop(memory_header, const.COMP_DEF_RULES_PARAM_VALS_TAG, memory_rules_param_vals)\n        context.merged_header = memory_header\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger.__init__","title":"__init__(self, catalog_interface) special","text":"

                                    Initialize catalog merger.

                                    Source code in trestle/core/catalog/catalog_merger.py
                                    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog merger.\"\"\"\n    self._catalog_interface = catalog_interface\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger.merge_catalog","title":"merge_catalog(self, catalog, replace_params)","text":"

                                    Merge the provided new catalog controls into the original catalog in this catalog interface.

                                    Parameters:

                                    Name Type Description Default catalog Catalog

                                    catalog containing controls that are merged into the current catalog of the interface

                                    required replace_params bool

                                    replace all params in the control with the new ones

                                    required

                                    Notes

                                    This is mainly to support the reading of a catalog from markdown. It allows retention of content such as metadata and backmatter, along with labels and other parameter attributes that aren't in markdown. The list of controls and group structure is specified by the markdown structure - but this doesn't allow controls to contain controls. Group lists are specified per directory.

                                    Reading the markdown tells you groups and controls in them - and groups in groups. Controls cannot change groups. If the control was in the original json, its parts are replaced, including its parameters. Only values may be specified. If no value specified, the value is unset in json.

                                    Source code in trestle/core/catalog/catalog_merger.py
                                    def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"\n    Merge the provided new catalog controls into the original catalog in this catalog interface.\n\n    Args:\n        catalog: catalog containing controls that are merged into the current catalog of the interface\n        replace_params: replace all params in the control with the new ones\n\n    Notes:\n        This is mainly to support the reading of a catalog from markdown.  It allows retention of content such as\n        metadata and backmatter, along with labels and other parameter attributes that aren't in markdown.\n        The list of controls and group structure is specified by the markdown structure - but this doesn't allow\n        controls to contain controls.  Group lists are specified per directory.\n\n        Reading the markdown tells you groups and controls in them - and groups in groups.\n        Controls cannot change groups.  If the control was in the original json, its parts are replaced,\n        including its parameters.  Only values may be specified.  If no value specified, the value is unset in json.\n    \"\"\"\n    cat_interface = CatalogInterface(catalog)\n    for src in cat_interface.get_all_controls_from_dict():\n        group_id, _, _ = cat_interface.get_group_info_by_control(src.id)\n        dest = self._catalog_interface.get_control(src.id)\n        if dest:\n            dest_group, _, _ = self._catalog_interface.get_group_info_by_control(dest.id)\n            if dest_group != group_id:\n                raise TrestleError(f'Markdown for control {src.id} has different group id.')\n            CatalogMerger.merge_controls(dest, src, replace_params)\n            self._catalog_interface.replace_control(dest)\n        else:\n            # this is a new control that isn't already in the merge destination\n            # need to add the control knowing its group must already exist\n            # get group info from an arbitrary control already present in group\n            _, control_handle = self._catalog_interface._find_control_in_group(group_id)\n            new_control_handle = copy.deepcopy(control_handle)\n            new_control_handle.control = src\n            # add the control and its handle to the param_dict\n            self._catalog_interface._control_dict[src.id] = new_control_handle  # type: ignore\n\n    # now need to cull any controls that are not in the src catalog\n    if cat_interface._control_dict is None:\n        handled_ids = None\n    else:\n        handled_ids = set(cat_interface._control_dict.keys())\n    orig_ids = set(self._catalog_interface._control_dict.keys())\n    extra_ids = orig_ids.difference(handled_ids)\n    for extra_id in sorted(extra_ids):\n        self._catalog_interface._control_dict.pop(extra_id)\n\n    self._catalog_interface.update_catalog_controls()\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger.merge_controls","title":"merge_controls(dest, src, replace_params) staticmethod","text":"

                                    Merge the src control into dest.

                                    Parameters:

                                    Name Type Description Default dest Control

                                    destination control into which content will be added

                                    required src Control

                                    source control with new content

                                    required replace_params bool

                                    replace the control params with the new ones

                                    required Source code in trestle/core/catalog/catalog_merger.py
                                    @staticmethod\ndef merge_controls(dest: cat.Control, src: cat.Control, replace_params: bool) -> None:\n\"\"\"\n    Merge the src control into dest.\n\n    Args:\n        dest: destination control into which content will be added\n        src: source control with new content\n        replace_params: replace the control params with the new ones\n    \"\"\"\n    ControlInterface.merge_parts(dest, src)\n    if replace_params:\n        dest.params = src.params\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/","title":"catalog_reader","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader","title":"trestle.core.catalog.catalog_reader","text":"

                                    Provide interface to read catalog from markdown back to OSCAL.

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader","title":" CatalogReader ","text":"

                                    Catalog reader.

                                    Catalog reader handles all operations related to reading catalog from markdown.

                                    Source code in trestle/core/catalog/catalog_reader.py
                                    class CatalogReader():\n\"\"\"\n    Catalog reader.\n\n    Catalog reader handles all operations related to\n    reading catalog from markdown.\n    \"\"\"\n\n    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog reader.\"\"\"\n        self._catalog_interface = catalog_interface\n\n    def read_additional_content(\n        self,\n        md_path: pathlib.Path,\n        required_sections_list: List[str],\n        label_map: Dict[str, Dict[str, str]],\n        sections_dict: Dict[str, str],\n        write_mode: bool\n    ) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read all markdown controls and return list of alters plus control param dict and param sort map.\"\"\"\n        alters_map: Dict[str, prof.Alter] = {}\n        final_param_dict: Dict[str, Any] = {}\n        param_sort_map: Dict[str, str] = {}\n        for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n            for control_file in group_path.glob('*.md'):\n                sort_id, control_alters, control_param_dict = ControlReader.read_editable_content(\n                    control_file,\n                    required_sections_list,\n                    label_map,\n                    sections_dict,\n                    write_mode\n                )\n                alters_map[sort_id] = control_alters\n                for param_id, param_dict in control_param_dict.items():\n                    # if profile_values are present, overwrite values with them\n                    if const.PROFILE_VALUES in param_dict:\n                        if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                            if not write_mode and const.REPLACE_ME_PLACEHOLDER in param_dict[const.PROFILE_VALUES]:\n                                param_dict[const.PROFILE_VALUES].remove(const.REPLACE_ME_PLACEHOLDER)\n                            if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                                param_dict[const.VALUES] = param_dict[const.PROFILE_VALUES]\n                        if not write_mode:\n                            param_dict.pop(const.PROFILE_VALUES)\n                    # verifies if at control profile edition the param value origin was modified\n                    # through the profile-param-value-origin tag\n                    if const.PROFILE_PARAM_VALUE_ORIGIN in param_dict:\n                        if param_dict[const.PROFILE_PARAM_VALUE_ORIGIN] != const.REPLACE_ME_PLACEHOLDER:\n                            param_dict[const.PARAM_VALUE_ORIGIN] = param_dict[const.PROFILE_PARAM_VALUE_ORIGIN]\n                            param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                        else:\n                            # removes replace me placeholder and profile-param-value-origin as it was not modified\n                            param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                            # validates param-value-origin is in dict to remove it\n                            # because a value wasn\u00b4t provided and it shouldn\u00b4t be inheriting value from parent\n                            if const.PARAM_VALUE_ORIGIN in param_dict:\n                                param_dict.pop(const.PARAM_VALUE_ORIGIN)\n                    final_param_dict[param_id] = param_dict\n                    param_sort_map[param_id] = sort_id\n        new_alters: List[prof.Alter] = []\n        # fill the alters according to the control sorting order\n        for key in sorted(alters_map.keys()):\n            new_alters.extend(alters_map[key])\n        return new_alters, final_param_dict, param_sort_map\n\n    def read_catalog_from_markdown(self, md_path: pathlib.Path, set_parameters_flag: bool) -> cat.Catalog:\n\"\"\"\n        Read the groups and catalog controls from the given directory.\n\n        This will overwrite the existing groups and controls in the catalog.\n        \"\"\"\n        id_map = CatalogInterface._get_group_ids_and_dirs(md_path)\n        groups: List[cat.Group] = []\n        # read each group dir\n        for group_id, group_dir in id_map.items():\n            control_list_raw = []\n            group_title = ''\n            # Need to get group title from at least one control in this directory\n            # All controls in dir should have same group title\n            # Set group title to the first one found and warn if different non-empty title appears\n            # Controls with empty group titles are tolerated but at least one title must be present or warning given\n            # The special group with no name that has the catalog as parent is just a list and has no title\n            for control_path in group_dir.glob('*.md'):\n                control, control_group_title = ControlReader.read_control(control_path, set_parameters_flag)\n                if control_group_title:\n                    if group_title:\n                        if control_group_title != group_title:\n                            logger.warning(\n                                f'Control {control.id} group title {control_group_title} differs from {group_title}'\n                            )\n                    else:\n                        group_title = control_group_title\n                control_list_raw.append(control)\n            control_list = sorted(control_list_raw, key=lambda control: ControlInterface.get_sort_id(control))\n            if group_id:\n                if not group_title:\n                    logger.warning(\n                        f'No group title found in controls for group {group_id}.  The title will be recovered if assembling into an existing catalog with the group title defined.'  # noqa E501\n                    )\n                new_group = cat.Group(id=group_id, title=group_title)\n                new_group.controls = none_if_empty(control_list)\n                groups.append(new_group)\n            else:\n                # if the list of controls has no group id it also has no title and is just the controls of the catalog\n                self._catalog_interface._catalog.controls = none_if_empty(control_list)\n        self._catalog_interface._catalog.groups = none_if_empty(groups)\n        self._catalog_interface._create_control_dict()\n        self._catalog_interface._catalog.params = none_if_empty(self._catalog_interface._catalog.params)\n        return self._catalog_interface._catalog\n\n    @staticmethod\n    def read_catalog_imp_reqs(md_path: pathlib.Path, context: ControlContext) -> List[comp.ImplementedRequirement]:\n\"\"\"Read the full set of control implemented requirements from markdown.\n\n        Args:\n            md_path: Path to the markdown control files, with directories for each group\n            context: Context for the operation\n\n        Returns:\n            List of implemented requirements gathered from each control\n\n        Notes:\n            As the controls are read into the catalog the needed components are added if not already available.\n            avail_comps provides the mapping of component name to the actual component.\n            This is only used during component assemble and only for updating one component\n        \"\"\"\n        imp_req_map: Dict[str, comp.ImplementedRequirement] = {}\n        for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n            for control_file in group_path.glob('*.md'):\n                sort_id, imp_req = ControlReader.read_implemented_requirement(control_file, context)\n                imp_req_map[sort_id] = imp_req\n        return [imp_req_map[key] for key in sorted(imp_req_map.keys())]\n\n    @staticmethod\n    def _get_imp_req_for_control(ssp: ossp.SystemSecurityPlan, control_id: str) -> ossp.ImplementedRequirement:\n        for imp_req in as_list(ssp.control_implementation.implemented_requirements):\n            if imp_req.control_id == control_id:\n                return imp_req\n        imp_req = gens.generate_sample_model(ossp.ImplementedRequirement)\n        imp_req.control_id = control_id\n        ssp.control_implementation.implemented_requirements = as_list(\n            ssp.control_implementation.implemented_requirements\n        )\n        ssp.control_implementation.implemented_requirements.append(imp_req)\n        return imp_req\n\n    @staticmethod\n    def _get_imp_req_for_statement(\n        ssp: ossp.SystemSecurityPlan, control_id: str, statement_id: str\n    ) -> ossp.ImplementedRequirement:\n        control_imp_req: Optional[ossp.ImplementedRequirement] = None\n        for imp_req in as_list(ssp.control_implementation.implemented_requirements):\n            if imp_req.control_id == control_id:\n                control_imp_req = imp_req\n                if statement_id in [stat.statement_id for stat in as_list(imp_req.statements)]:\n                    return imp_req\n        # we didn't find imp_req with statement so need to make statement and/or imp_req\n        if not control_imp_req:\n            control_imp_req = gens.generate_sample_model(ossp.ImplementedRequirement)\n            control_imp_req.control_id = control_id\n            control_imp_req.statements = None\n            ssp.control_implementation.implemented_requirements = as_list(\n                ssp.control_implementation.implemented_requirements\n            )\n            ssp.control_implementation.implemented_requirements.append(control_imp_req)\n        statement = gens.generate_sample_model(ossp.Statement)\n        statement.statement_id = statement_id\n        statement.by_components = None\n        control_imp_req.statements = as_list(control_imp_req.statements)\n        control_imp_req.statements.append(statement)\n        return control_imp_req\n\n    @staticmethod\n    def _get_by_comp_from_imp_req(\n        imp_req: ossp.ImplementedRequirement, statement_id: str, comp_uuid: str\n    ) -> ossp.ByComponent:\n        if statement_id:\n            for statement in as_list(imp_req.statements):\n                if statement.statement_id == statement_id:\n                    for by_comp in as_list(statement.by_components):\n                        if by_comp.component_uuid == comp_uuid:\n                            return by_comp\n                    # didnt find bycomp so need to make one\n                    by_comp = gens.generate_sample_model(ossp.ByComponent)\n                    by_comp.component_uuid = comp_uuid\n                    by_comp.implementation_status = com.ImplementationStatus(state=const.STATUS_PLANNED)\n                    statement.by_components = as_list(statement.by_components)\n                    statement.by_components.append(by_comp)\n                    return by_comp\n        else:\n            for by_comp in as_list(imp_req.by_components):\n                if by_comp.component_uuid == comp_uuid:\n                    return by_comp\n            by_comp = gens.generate_sample_model(ossp.ByComponent)\n            by_comp.component_uuid = comp_uuid\n            by_comp.implementation_status = com.ImplementationStatus(state=const.STATUS_PLANNED)\n            imp_req.by_components = as_list(imp_req.by_components)\n            imp_req.by_components.append(by_comp)\n            return by_comp\n        raise TrestleError(f'Internal error seeking by_comp for component {comp_uuid} and statement {statement_id}')\n\n    @staticmethod\n    def _read_comp_info_from_md(control_file_path: pathlib.Path,\n                                context: ControlContext) -> Tuple[Dict[str, Any], CompDict]:\n        md_header = {}\n        comp_dict = {}\n        if control_file_path.exists():\n            md_header, comp_dict = ControlReader.read_control_info_from_md(control_file_path, context)\n        return md_header, comp_dict\n\n    @staticmethod\n    def _update_ssp_with_comp_info(\n        ssp: ossp.SystemSecurityPlan,\n        control_id: str,\n        gen_comp: generic.GenericComponent,\n        comp_info_dict: Dict[str, ComponentImpInfo],\n        part_id_map_by_label: Dict[str, Dict[str, str]]\n    ) -> None:\n        # get imp req for control and find one with by_comp, creating if needed\n        imp_req = CatalogReader._get_imp_req_for_control(ssp, control_id)\n        # if control has no parts it will not have part id map and bycomps will go at control level\n        control_part_id_map = part_id_map_by_label.get(control_id, {})\n        for label, comp_info in comp_info_dict.items():\n            part_id = control_part_id_map.get(label, '')\n            by_comp = CatalogReader._get_by_comp_from_imp_req(imp_req, part_id, gen_comp.uuid)\n            by_comp.description = comp_info.prose\n            by_comp.implementation_status = comp_info.status\n\n    @staticmethod\n    def _insert_set_param_into_by_comps(\n        item: Union[ossp.ImplementedRequirement, ossp.ByComponent],\n        rule_id: str,\n        param_name: str,\n        param_values: List[str],\n        comp_uuid: str\n    ) -> None:\n        for by_comp in as_list(item.by_components):\n            if by_comp.component_uuid == comp_uuid:\n                for prop in as_list(by_comp.props):\n                    if prop.name == const.RULE_ID and prop.value == rule_id:\n                        found = False\n                        for sp in as_list(by_comp.set_parameters):\n                            if sp.param_id == param_name:\n                                sp.values = param_values\n                                found = True\n                                break\n                        if not found:\n                            sp = ossp.SetParameter(param_id=param_name, values=param_values)\n                            by_comp.set_parameters = as_list(by_comp.set_parameters)\n                            by_comp.set_parameters.append(sp)\n\n    @staticmethod\n    def _insert_param_dict_in_imp_req(\n        imp_req: ossp.ImplementedRequirement,\n        param_dict: Dict[str, str],\n        comp_name: str,\n        md_header: Dict[str, Dict[str, str]],\n        comp_uuid: str\n    ):\n\"\"\"Insert the param in the by_comps that are supported by the rule.\"\"\"\n        # given param name find rule_id in comp name header entry\n        # then find all statements with by_comp that have that rule id in props\n        rules_dict = md_header.get(const.RULES_PARAMS_TAG, {})\n        comp_rules_params = rules_dict.get(comp_name, [])\n        param_name = param_dict['name']\n        param_values = param_dict['values']\n        for comp_rule_param in comp_rules_params:\n            if comp_rule_param['name'] == param_name:\n                rule_id = comp_rule_param[const.HEADER_RULE_ID]\n                CatalogReader._insert_set_param_into_by_comps(imp_req, rule_id, param_name, param_values, comp_uuid)\n                for statement in as_list(imp_req.statements):\n                    CatalogReader._insert_set_param_into_by_comps(\n                        statement, rule_id, param_name, param_values, comp_uuid\n                    )\n\n    @staticmethod\n    def _add_set_params_to_item(param_dict: Dict[str, str], item: TypeWithSetParams, param_id: str) -> None:\n        value_list = param_dict[const.SSP_VALUES]\n        param_values = value_list\n        new_sp_list = []\n        for sp in as_list(item.set_parameters):\n            if sp.param_id != param_id:\n                new_sp_list.append(sp)\n        item.set_parameters = new_sp_list\n        item.set_parameters.append(ossp.SetParameter(param_id=param_id, values=param_values))\n\n    @staticmethod\n    def _add_props_to_imp_req(\n        control_id: str,\n        part_id_map_by_label: Dict[str, Dict[str, str]],\n        yaml_header: Dict[str, Any],\n        imp_req: ossp.ImplementedRequirement\n    ) -> None:\n\"\"\"Add the props from the yaml header to the imp_req.\"\"\"\n        control_part_id_map = part_id_map_by_label.get(control_id, {})\n        props, props_by_id = ControlReader.get_props_list(control_id, control_part_id_map, yaml_header)\n        # add the props at control level\n        if props:\n            imp_req.props = as_list(imp_req.props)\n            imp_req.props.extend(props)\n\n        # add the props at the part level\n        for label, part_id in control_part_id_map.items():\n            props = props_by_id.get(label, [])\n            if not props:\n                continue\n            for statement in as_list(imp_req.statements):\n                if statement.statement_id == part_id:\n                    statement.props = as_list(statement.props)\n                    statement.props.extend(props)\n\n    @staticmethod\n    def _update_ssp_with_md_header(\n        ssp: ossp.SystemSecurityPlan,\n        control_id: str,\n        comp_dict: Dict[str, generic.GenericComponent],\n        part_label_to_id_map: Dict[str, Dict[str, str]],\n        md_header: Dict[str, Dict[str, str]]\n    ) -> None:\n\"\"\"Update the ssp with info from the header of an ssp control markdown file.\"\"\"\n        # rules param vals go in bycomps of imp_req\n        # param vals go directly in imp_req\n        rules_param_vals_dict = md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {})\n        imp_req = CatalogReader._get_imp_req_for_control(ssp, control_id)\n        for comp_name, param_dict_list in rules_param_vals_dict.items():\n            for param_dict in as_list(param_dict_list):\n                if const.SSP_VALUES in param_dict:\n                    param_dict['values'] = param_dict['ssp-values']\n                CatalogReader._insert_param_dict_in_imp_req(\n                    imp_req, param_dict, comp_name, md_header, comp_dict[comp_name].uuid\n                )\n        param_vals_dict = md_header.get(const.SET_PARAMS_TAG, {})\n        for param_id, param_dict in param_vals_dict.items():\n            if const.SSP_VALUES in param_dict:\n                CatalogReader._add_set_params_to_item(param_dict, imp_req, param_id)\n\n        CatalogReader._add_props_to_imp_req(control_id, part_label_to_id_map, md_header, imp_req)\n\n    @staticmethod\n    def read_ssp_md_content(\n        md_path: pathlib.Path,\n        ssp: ossp.SystemSecurityPlan,\n        comp_dict: Dict[str, generic.GenericComponent],\n        part_id_map_by_label: Dict[str, Dict[str, str]],\n        context: ControlContext\n    ) -> None:\n\"\"\"\n        Read md content into the ssp.\n\n        Args:\n            md_path: path to the catalog markdown\n            ssp: ssp in which to insert the md content\n            comp_dict: map of component name to component\n            part_id_map_by_label: map label to part_id of control\n            context: control context for the procedure\n\n        Notes:\n            The ssp should already contain info from the comp defs and this fills in selected content from md.\n            The only content read from md is:\n                ssp values in the comp def rules param vals of the header\n                ssp values in the set-params of the header\n                all prose for implementaton responses\n                all status values\n            ssp has components but may not have all needed imp reqs and bycomps\n            know controlid and comp name in comp_dict\n        \"\"\"\n        for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n            for control_file in group_path.glob('*.md'):\n                skip = False\n                for file in control_file.parents:\n                    if file.name == const.INHERITANCE_VIEW_DIR:\n                        skip = True\n                        break\n                if skip:\n                    continue\n\n                control_id = control_file.stem\n\n                md_header, control_comp_dict = CatalogReader._read_comp_info_from_md(control_file, context)\n\n                for comp_name, comp_info_dict in control_comp_dict.items():\n                    if comp_name not in comp_dict:\n                        err_msg = f'Control {control_id} references component {comp_name} not defined in a component-definition.'  # noqa E501\n                        # give added guidance if no comp defs were specified at command line\n                        if not context.comp_def_name_list:\n                            err_msg += '  Please specify the names of any component-definitions needed for assembly.'\n                        raise TrestleError(err_msg)\n                    CatalogReader._update_ssp_with_comp_info(\n                        ssp, control_id, comp_dict[comp_name], comp_info_dict, part_id_map_by_label\n                    )\n                CatalogReader._update_ssp_with_md_header(ssp, control_id, comp_dict, part_id_map_by_label, md_header)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.__init__","title":"__init__(self, catalog_interface) special","text":"

                                    Initialize catalog reader.

                                    Source code in trestle/core/catalog/catalog_reader.py
                                    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog reader.\"\"\"\n    self._catalog_interface = catalog_interface\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_additional_content","title":"read_additional_content(self, md_path, required_sections_list, label_map, sections_dict, write_mode)","text":"

                                    Read all markdown controls and return list of alters plus control param dict and param sort map.

                                    Source code in trestle/core/catalog/catalog_reader.py
                                    def read_additional_content(\n    self,\n    md_path: pathlib.Path,\n    required_sections_list: List[str],\n    label_map: Dict[str, Dict[str, str]],\n    sections_dict: Dict[str, str],\n    write_mode: bool\n) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read all markdown controls and return list of alters plus control param dict and param sort map.\"\"\"\n    alters_map: Dict[str, prof.Alter] = {}\n    final_param_dict: Dict[str, Any] = {}\n    param_sort_map: Dict[str, str] = {}\n    for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n        for control_file in group_path.glob('*.md'):\n            sort_id, control_alters, control_param_dict = ControlReader.read_editable_content(\n                control_file,\n                required_sections_list,\n                label_map,\n                sections_dict,\n                write_mode\n            )\n            alters_map[sort_id] = control_alters\n            for param_id, param_dict in control_param_dict.items():\n                # if profile_values are present, overwrite values with them\n                if const.PROFILE_VALUES in param_dict:\n                    if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                        if not write_mode and const.REPLACE_ME_PLACEHOLDER in param_dict[const.PROFILE_VALUES]:\n                            param_dict[const.PROFILE_VALUES].remove(const.REPLACE_ME_PLACEHOLDER)\n                        if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                            param_dict[const.VALUES] = param_dict[const.PROFILE_VALUES]\n                    if not write_mode:\n                        param_dict.pop(const.PROFILE_VALUES)\n                # verifies if at control profile edition the param value origin was modified\n                # through the profile-param-value-origin tag\n                if const.PROFILE_PARAM_VALUE_ORIGIN in param_dict:\n                    if param_dict[const.PROFILE_PARAM_VALUE_ORIGIN] != const.REPLACE_ME_PLACEHOLDER:\n                        param_dict[const.PARAM_VALUE_ORIGIN] = param_dict[const.PROFILE_PARAM_VALUE_ORIGIN]\n                        param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                    else:\n                        # removes replace me placeholder and profile-param-value-origin as it was not modified\n                        param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                        # validates param-value-origin is in dict to remove it\n                        # because a value wasn\u00b4t provided and it shouldn\u00b4t be inheriting value from parent\n                        if const.PARAM_VALUE_ORIGIN in param_dict:\n                            param_dict.pop(const.PARAM_VALUE_ORIGIN)\n                final_param_dict[param_id] = param_dict\n                param_sort_map[param_id] = sort_id\n    new_alters: List[prof.Alter] = []\n    # fill the alters according to the control sorting order\n    for key in sorted(alters_map.keys()):\n        new_alters.extend(alters_map[key])\n    return new_alters, final_param_dict, param_sort_map\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_catalog_from_markdown","title":"read_catalog_from_markdown(self, md_path, set_parameters_flag)","text":"

                                    Read the groups and catalog controls from the given directory.

                                    This will overwrite the existing groups and controls in the catalog.

                                    Source code in trestle/core/catalog/catalog_reader.py
                                    def read_catalog_from_markdown(self, md_path: pathlib.Path, set_parameters_flag: bool) -> cat.Catalog:\n\"\"\"\n    Read the groups and catalog controls from the given directory.\n\n    This will overwrite the existing groups and controls in the catalog.\n    \"\"\"\n    id_map = CatalogInterface._get_group_ids_and_dirs(md_path)\n    groups: List[cat.Group] = []\n    # read each group dir\n    for group_id, group_dir in id_map.items():\n        control_list_raw = []\n        group_title = ''\n        # Need to get group title from at least one control in this directory\n        # All controls in dir should have same group title\n        # Set group title to the first one found and warn if different non-empty title appears\n        # Controls with empty group titles are tolerated but at least one title must be present or warning given\n        # The special group with no name that has the catalog as parent is just a list and has no title\n        for control_path in group_dir.glob('*.md'):\n            control, control_group_title = ControlReader.read_control(control_path, set_parameters_flag)\n            if control_group_title:\n                if group_title:\n                    if control_group_title != group_title:\n                        logger.warning(\n                            f'Control {control.id} group title {control_group_title} differs from {group_title}'\n                        )\n                else:\n                    group_title = control_group_title\n            control_list_raw.append(control)\n        control_list = sorted(control_list_raw, key=lambda control: ControlInterface.get_sort_id(control))\n        if group_id:\n            if not group_title:\n                logger.warning(\n                    f'No group title found in controls for group {group_id}.  The title will be recovered if assembling into an existing catalog with the group title defined.'  # noqa E501\n                )\n            new_group = cat.Group(id=group_id, title=group_title)\n            new_group.controls = none_if_empty(control_list)\n            groups.append(new_group)\n        else:\n            # if the list of controls has no group id it also has no title and is just the controls of the catalog\n            self._catalog_interface._catalog.controls = none_if_empty(control_list)\n    self._catalog_interface._catalog.groups = none_if_empty(groups)\n    self._catalog_interface._create_control_dict()\n    self._catalog_interface._catalog.params = none_if_empty(self._catalog_interface._catalog.params)\n    return self._catalog_interface._catalog\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_catalog_imp_reqs","title":"read_catalog_imp_reqs(md_path, context) staticmethod","text":"

                                    Read the full set of control implemented requirements from markdown.

                                    Parameters:

                                    Name Type Description Default md_path Path

                                    Path to the markdown control files, with directories for each group

                                    required context ControlContext

                                    Context for the operation

                                    required

                                    Returns:

                                    Type Description List[trestle.oscal.component.ImplementedRequirement]

                                    List of implemented requirements gathered from each control

                                    Notes

                                    As the controls are read into the catalog the needed components are added if not already available. avail_comps provides the mapping of component name to the actual component. This is only used during component assemble and only for updating one component

                                    Source code in trestle/core/catalog/catalog_reader.py
                                    @staticmethod\ndef read_catalog_imp_reqs(md_path: pathlib.Path, context: ControlContext) -> List[comp.ImplementedRequirement]:\n\"\"\"Read the full set of control implemented requirements from markdown.\n\n    Args:\n        md_path: Path to the markdown control files, with directories for each group\n        context: Context for the operation\n\n    Returns:\n        List of implemented requirements gathered from each control\n\n    Notes:\n        As the controls are read into the catalog the needed components are added if not already available.\n        avail_comps provides the mapping of component name to the actual component.\n        This is only used during component assemble and only for updating one component\n    \"\"\"\n    imp_req_map: Dict[str, comp.ImplementedRequirement] = {}\n    for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n        for control_file in group_path.glob('*.md'):\n            sort_id, imp_req = ControlReader.read_implemented_requirement(control_file, context)\n            imp_req_map[sort_id] = imp_req\n    return [imp_req_map[key] for key in sorted(imp_req_map.keys())]\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_ssp_md_content","title":"read_ssp_md_content(md_path, ssp, comp_dict, part_id_map_by_label, context) staticmethod","text":"

                                    Read md content into the ssp.

                                    Parameters:

                                    Name Type Description Default md_path Path

                                    path to the catalog markdown

                                    required ssp SystemSecurityPlan

                                    ssp in which to insert the md content

                                    required comp_dict Dict[str, trestle.core.generic_oscal.GenericComponent]

                                    map of component name to component

                                    required part_id_map_by_label Dict[str, Dict[str, str]]

                                    map label to part_id of control

                                    required context ControlContext

                                    control context for the procedure

                                    required

                                    Notes

                                    The ssp should already contain info from the comp defs and this fills in selected content from md. The only content read from md is: ssp values in the comp def rules param vals of the header ssp values in the set-params of the header all prose for implementaton responses all status values ssp has components but may not have all needed imp reqs and bycomps know controlid and comp name in comp_dict

                                    Source code in trestle/core/catalog/catalog_reader.py
                                    @staticmethod\ndef read_ssp_md_content(\n    md_path: pathlib.Path,\n    ssp: ossp.SystemSecurityPlan,\n    comp_dict: Dict[str, generic.GenericComponent],\n    part_id_map_by_label: Dict[str, Dict[str, str]],\n    context: ControlContext\n) -> None:\n\"\"\"\n    Read md content into the ssp.\n\n    Args:\n        md_path: path to the catalog markdown\n        ssp: ssp in which to insert the md content\n        comp_dict: map of component name to component\n        part_id_map_by_label: map label to part_id of control\n        context: control context for the procedure\n\n    Notes:\n        The ssp should already contain info from the comp defs and this fills in selected content from md.\n        The only content read from md is:\n            ssp values in the comp def rules param vals of the header\n            ssp values in the set-params of the header\n            all prose for implementaton responses\n            all status values\n        ssp has components but may not have all needed imp reqs and bycomps\n        know controlid and comp name in comp_dict\n    \"\"\"\n    for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n        for control_file in group_path.glob('*.md'):\n            skip = False\n            for file in control_file.parents:\n                if file.name == const.INHERITANCE_VIEW_DIR:\n                    skip = True\n                    break\n            if skip:\n                continue\n\n            control_id = control_file.stem\n\n            md_header, control_comp_dict = CatalogReader._read_comp_info_from_md(control_file, context)\n\n            for comp_name, comp_info_dict in control_comp_dict.items():\n                if comp_name not in comp_dict:\n                    err_msg = f'Control {control_id} references component {comp_name} not defined in a component-definition.'  # noqa E501\n                    # give added guidance if no comp defs were specified at command line\n                    if not context.comp_def_name_list:\n                        err_msg += '  Please specify the names of any component-definitions needed for assembly.'\n                    raise TrestleError(err_msg)\n                CatalogReader._update_ssp_with_comp_info(\n                    ssp, control_id, comp_dict[comp_name], comp_info_dict, part_id_map_by_label\n                )\n            CatalogReader._update_ssp_with_md_header(ssp, control_id, comp_dict, part_id_map_by_label, md_header)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/","title":"catalog_writer","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer","title":"trestle.core.catalog.catalog_writer","text":"

                                    Provide interface to write OSCAL catalog to markdown.

                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter","title":" CatalogWriter ","text":"

                                    Catalog writer.

                                    Catalog writer handles all operation related to writing catalog to markdown.

                                    Source code in trestle/core/catalog/catalog_writer.py
                                    class CatalogWriter():\n\"\"\"\n    Catalog writer.\n\n    Catalog writer handles all operation related to writing\n    catalog to markdown.\n    \"\"\"\n\n    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog writer.\"\"\"\n        self._catalog_interface = catalog_interface\n\n    def write_catalog_as_profile_markdown(\n        self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]], md_alters: List[prof.Alter]\n    ) -> None:\n\"\"\"Write out the catalog as profile markdown.\"\"\"\n        # Get the list of params for this profile from its set_params\n        # this is just from the set_params\n        profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n\n        # write out the controls\n        for control in self._catalog_interface.get_all_controls_from_catalog(True):\n            # here we do special handling of how set-parameters merge with the yaml header\n            new_context = ControlContext.clone(context)\n            new_context.merged_header = {}\n\n            new_context = self._add_inherited_props_to_header(new_context, control.id)\n\n            # get all params and vals for this control from the resolved profile catalog with block adds in effect\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n\n            if set_param_dict:\n                self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n            elif const.SET_PARAMS_TAG in new_context.merged_header:\n                # need to cull any params that are not in control\n                pop_list: List[str] = []\n                for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                    if key not in control_param_dict:\n                        pop_list.append(key)\n                for pop in pop_list:\n                    new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n            found_control_alters = [alter for alter in md_alters if alter.control_id == control.id]\n\n            self._write_control_into_dir(new_context, control, part_id_map, found_control_alters)\n\n    def _add_inherited_props_to_header(self, context: ControlContext, control_id: str) -> ControlContext:\n\"\"\"Add inherited props to the merged header under inherited tag.\"\"\"\n        if context.inherited_props:\n            inherited_props = context.inherited_props.get(control_id, None)\n            if inherited_props:\n                # build set in order of list so that duplicates will have final value stick, then convert to list\n                unique_props = list({prop['name']: prop for prop in inherited_props}.values())\n                context.merged_header[const.TRESTLE_INHERITED_PROPS_TAG] = unique_props\n\n        return context\n\n    def _add_set_params_from_cli_yaml_header_to_header(\n        self, context: ControlContext, set_param_dict: Dict[str, str], control_param_dict: Dict[str, common.Parameter]\n    ):\n\"\"\"\n        Add set parameters from the provided cli yaml header to the merged header.\n\n        If overwrite-header-value flag is given\n            - Set-parameters in set_param_dict will be overwritten with those in cli yaml header\n            - No new params from the cli yaml header will be added <- TODO: Is this correct?\n        If ohv flag is NOT given :\n            - Set-parameters from the cli yaml header will be added\n            - Will not overwrite params that are already in set_param_dict\n        \"\"\"\n        if const.SET_PARAMS_TAG not in context.cli_yaml_header:\n            context.cli_yaml_header[const.SET_PARAMS_TAG] = {}\n\n        if context.cli_yaml_header:\n            if context.overwrite_header_values:\n                # update the control params with new values\n                for key, value in context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict:\n                        set_param_dict[key] = value\n            else:\n                # update the control params with any values in yaml header not set in control\n                # need to maintain order in the set_param_dict\n                for key, value in context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict and key not in set_param_dict:\n                        set_param_dict[key] = value\n        context.merged_header[const.SET_PARAMS_TAG] = set_param_dict\n\n    def _construct_set_parameters_dict(\n        self,\n        profile_set_param_dict: Dict[str, common.Parameter],\n        control_param_dict: Dict[str, Dict[str, Any]],\n        context: ControlContext\n    ) -> Dict[str, Dict[str, Any]]:\n\"\"\"\n        Build set-parameters dictionary from the given profile.modify.set-parameters and control.params.\n\n        Resulting dictionary will have:\n        - All parameters from the control where:\n            - If control_param in profile.modify.set_params:\n                - Display name (if exists) - from profile\n                - Profile-values - from profile\n                - Values - from control\n            - If control_param is not in profile.modify.set_params:\n                - Values - from control\n        \"\"\"\n        set_param_dict: Dict[str, Dict[str, Any]] = {}\n        for param_id, param_dict in control_param_dict.items():\n            # if the param is in the full_param_dict, load its contents first and mark as profile-values\n            display_name = ''\n            param_value_origin, _ = CatalogInterface._get_param_value_origin_and_ns(param_dict)\n            prof_param_value_origin = ''\n            if param_id in profile_set_param_dict:\n                # get the param from the profile set_param\n                param = profile_set_param_dict[param_id]\n                display_name, _ = CatalogInterface._get_display_name_and_ns(param)\n                prof_param_value_origin, _ = CatalogInterface._get_param_value_origin_and_ns(param)\n                # assign its contents to the dict\n                new_dict = ModelUtils.parameter_to_dict(param, True)\n                if const.VALUES in new_dict:\n                    if context.purpose == ContextPurpose.PROFILE:\n                        new_dict[const.PROFILE_VALUES] = new_dict[const.VALUES]\n                        new_dict.pop(const.VALUES)\n                # validates if parent profile has param-value-origin field\n                if param_value_origin != '' and param_value_origin is not None:\n                    if context.purpose == ContextPurpose.PROFILE:\n                        new_dict[const.PARAM_VALUE_ORIGIN] = param_value_origin\n                # validates if current profile has param-value-origin field and\n                # adds it to prof-param-value-origin\n                if prof_param_value_origin != '' and prof_param_value_origin is not None:\n                    if context.purpose == ContextPurpose.PROFILE:\n                        new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = prof_param_value_origin\n                else:\n                    new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = const.REPLACE_ME_PLACEHOLDER\n                # then insert the original, incoming values as values\n                if param_id in control_param_dict:\n                    orig_param = control_param_dict[param_id]\n                    orig_dict = ModelUtils.parameter_to_dict(orig_param, True)\n                    # pull only the values from the actual control dict\n                    # all the other elements are from the profile set_param\n                    new_dict[const.VALUES] = orig_dict.get(const.VALUES, None)\n                    new_dict[const.GUIDELINES] = orig_dict.get(const.GUIDELINES, None)\n                    if new_dict[const.VALUES] is None:\n                        new_dict.pop(const.VALUES)\n                    if new_dict[const.GUIDELINES] is None:\n                        new_dict.pop(const.GUIDELINES)\n            else:\n                # if the profile doesnt change this param at all, show it in the header with values\n                tmp_dict = ModelUtils.parameter_to_dict(param_dict, True)\n                values = tmp_dict.get('values', None)\n                # if values are None then don\u00b4t display them in the markdown\n                if values is not None:\n                    new_dict = {\n                        'id': param_id,\n                        'values': values,\n                    }\n                else:\n                    new_dict = {\n                        'id': param_id,\n                    }\n                new_dict[const.PROFILE_VALUES] = [const.REPLACE_ME_PLACEHOLDER]\n                new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = const.REPLACE_ME_PLACEHOLDER\n            if param_value_origin is not None:\n                if context.purpose == ContextPurpose.PROFILE:\n                    new_dict[const.PARAM_VALUE_ORIGIN] = param_value_origin\n            new_dict.pop('id', None)\n            # validates if there are aggregated parameter values to the current parameter\n            aggregated_props = [prop for prop in as_list(param_dict.props) if prop.name == const.AGGREGATES]\n            if aggregated_props != []:\n                props_to_add = []\n                for prop in aggregated_props:\n                    props_to_add.append(prop.value)\n                new_dict[const.AGGREGATES] = props_to_add\n                new_dict.pop(const.PROFILE_VALUES, None)\n            alt_identifier = [prop for prop in as_list(param_dict.props) if prop.name == const.ALT_IDENTIFIER]\n            if alt_identifier != []:\n                new_dict[const.ALT_IDENTIFIER] = alt_identifier[0].value\n            # adds display name, if no display name then do not add to dict\n            if display_name != '' and display_name is not None:\n                new_dict[const.DISPLAY_NAME] = display_name\n            key_order = (\n                const.LABEL,\n                const.GUIDELINES,\n                const.VALUES,\n                const.AGGREGATES,\n                const.ALT_IDENTIFIER,\n                const.DISPLAY_NAME,\n                const.PROFILE_VALUES,\n                const.PARAM_VALUE_ORIGIN,\n                const.PROFILE_PARAM_VALUE_ORIGIN\n            )\n            ordered_dict = {k: new_dict[k] for k in key_order if k in new_dict.keys()}\n            set_param_dict[param_id] = ordered_dict\n\n        return set_param_dict\n\n    @staticmethod\n    def _fixup_param_dicts(context: ControlContext) -> None:\n\"\"\"Merge info in the rules params dict and the rules param vals dict.\"\"\"\n        for comp_name, comp_dict in context.rules_params_dict.items():\n            rules_dict = context.rules_dict.get(comp_name, {})\n            for rule_id, params_list in comp_dict.items():\n                for param in params_list:\n                    rule_name = deep_get(rules_dict, [rule_id, 'name'], 'unknown_rule_name')\n                    param[const.HEADER_RULE_ID] = rule_name\n\n    def write_catalog_as_ssp_markdown(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"\n        Write out the catalog as component markdown.\n\n        Already have resolved profile catalog, but with no setparams from compdefs\n        Load all control level rules and param values based on compdefs and profile values\n\n        In memory:\n        for each compdef:\n            for each comp:\n                load top level rules\n                for each control_imp:\n                    load set-params\n                    for each imp_req (bound to 1 control):\n                        load set-params\n                        load control level rules and status\n                        load part level rules and status\n                        add as compinfo to control comp_dict\n\n        \"\"\"\n        # generate rule and param info from the components\n        self._catalog_interface.generate_control_rule_info(part_id_map, context)\n\n        # now have all rules in context.rules_dict and all rules_params in context.rules_params_dict\n        # all set-params per component for each control are in the cat interface\n        # all comp-infos by control and part are in the cat interface\n        #\n        # can now write out catalog and pull from the markdown:\n        # header for param values to set during assem\n        # prose and status for This System\n        # status for all parts that still have rules\n\n        CatalogWriter._fixup_param_dicts(context)\n\n        # remove items left after above loop\n        context.component = None\n        context.comp_name = None\n\n        # get param_dict of set_params in profile\n        profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n        catalog_merger = CatalogMerger(self._catalog_interface)\n        for control in self._catalog_interface.get_all_controls_from_dict():\n            control_id = control.id\n            context.comp_dict = self._catalog_interface._control_comp_dicts.get(control_id, {})\n            control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control_id)\n            control_file_path.parent.mkdir(exist_ok=True, parents=True)\n            # the catalog interface is from the resolved profile catalog\n            control = self._catalog_interface.get_control(control_id)\n            _, group_title, _ = self._catalog_interface.get_group_info_by_control(control_id)\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n            new_context = ControlContext.clone(context)\n\n            if set_param_dict:\n                self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n            elif const.SET_PARAMS_TAG in new_context.merged_header:\n                # need to cull any params that are not in control\n                pop_list: List[str] = []\n                for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                    if key not in control_param_dict:\n                        pop_list.append(key)\n                for pop in pop_list:\n                    new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n            # merge the md_header and md_comp_dict with info in cat_interface for this control in new_context\n            catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n            if const.COMP_DEF_RULES_PARAM_VALS_TAG in new_context.merged_header:\n                for _, param_list in new_context.merged_header[const.COMP_DEF_RULES_PARAM_VALS_TAG].items():\n                    for param_dict in param_list:\n                        param_dict.pop(const.HEADER_RULE_ID, None)\n\n            control_writer = ControlWriter()\n            control_writer.write_control_for_editing(\n                new_context, control, control_file_path.parent, group_title, part_id_map, []\n            )\n\n    def write_catalog_as_component_markdown(\n        self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]\n    ) -> None:\n\"\"\"Write out the catalog as component markdown.\"\"\"\n        context.rules_dict = {}\n        context.rules_params_dict = {}\n\n        def _update_values(set_param: comp.SetParameter, control_param_dict) -> None:\n            # set the param values based on the control_param_dict if available\n            if set_param.param_id in control_param_dict:\n                control_param_dict[set_param.param_id] = set_param\n\n        control_ids_in_comp_imp = [\n            imp_req.control_id for imp_req in as_list(context.control_implementation.implemented_requirements)\n        ]\n\n        missing_controls = set(control_ids_in_comp_imp).difference(self._catalog_interface.get_control_ids())\n        if missing_controls:\n            logger.warning(f'Component {context.comp_name} references controls {missing_controls} not in profile.')\n\n        # get top level rule info applying to all controls\n        comp_rules_dict, comp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(context.component)  # noqa E501\n        context.rules_dict[context.comp_name] = comp_rules_dict\n        context.rules_params_dict[context.comp_name] = comp_rules_params_dict\n        for control_imp in as_list(context.component.control_implementations):\n            control_imp_rules_dict, control_imp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)  # noqa E501\n            context.rules_dict[context.comp_name].update(control_imp_rules_dict)\n            comp_rules_params_dict = context.rules_params_dict.get(context.comp_name, {})\n            comp_rules_params_dict.update(control_imp_rules_params_dict)\n            context.rules_params_dict[context.comp_name].update(comp_rules_params_dict)\n            ci_set_params = ControlInterface.get_set_params_from_item(control_imp)\n            for imp_req in as_list(control_imp.implemented_requirements):\n                control_part_id_map = part_id_map.get(imp_req.control_id, {})\n                control_rules, statement_rules, _ = ControlInterface.get_rule_list_for_imp_req(imp_req)\n                if control_rules or statement_rules:\n                    if control_rules:\n                        status = ControlInterface.get_status_from_props(imp_req)\n                        comp_info = ComponentImpInfo(imp_req.description, control_rules, [], status)\n                        self._catalog_interface.add_comp_info(imp_req.control_id, context.comp_name, '', comp_info)\n                    set_params = copy.deepcopy(ci_set_params)\n                    set_params.update(ControlInterface.get_set_params_from_item(imp_req))\n                    for set_param in set_params.values():\n                        self._catalog_interface.add_comp_set_param(imp_req.control_id, context.comp_name, set_param)\n                    for statement in as_list(imp_req.statements):\n                        rule_list, _ = ControlInterface.get_rule_list_for_item(statement)\n                        if rule_list:\n                            status = ControlInterface.get_status_from_props(statement)\n                            if statement.statement_id not in control_part_id_map:\n                                label = statement.statement_id\n                                logger.warning(\n                                    f'No statement label found for statement id {label}.  Defaulting to {label}.'\n                                )\n                            else:\n                                label = control_part_id_map[statement.statement_id]\n                            comp_info = ComponentImpInfo(statement.description, rule_list, [], status)\n                            self._catalog_interface.add_comp_info(\n                                imp_req.control_id, context.comp_name, label, comp_info\n                            )\n\n        catalog_merger = CatalogMerger(self._catalog_interface)\n\n        for control in self._catalog_interface.get_all_controls_from_catalog(True):\n            if control.id in control_ids_in_comp_imp:\n                context.comp_dict = self._catalog_interface.get_comp_info(control.id)\n                new_context = ControlContext.clone(context)\n                # get the resolved catalog values for the control params\n                control_param_dict = ControlInterface.get_control_param_dict(control, False)\n                # update them with values in the ci\n                for set_param in as_list(new_context.control_implementation.set_parameters):\n                    _update_values(set_param, control_param_dict)\n                # update them with values in the imp_req\n                for imp_req in as_list(new_context.control_implementation.implemented_requirements):\n                    if imp_req.control_id == control.id:\n                        for set_param in as_list(imp_req.set_parameters):\n                            _update_values(set_param, control_param_dict)\n\n                # insert the param values into the header\n                if control_param_dict:\n                    new_context.merged_header[const.PARAM_VALUES_TAG] = {}\n                    for key, param in control_param_dict.items():\n                        new_context.merged_header[const.PARAM_VALUES_TAG][key] = none_if_empty(\n                            ControlInterface._param_values_as_str_list(param)\n                        )\n                # merge the md_header and md_comp_dict with info in cat_interface for this control\n                control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control.id)\n                catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n                self._write_control_into_dir(new_context, control, part_id_map, [])\n\n    def write_catalog_as_catalog(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"Write the catalog as a simple catalog.\"\"\"\n        # write out the controls\n        for control in self._catalog_interface.get_all_controls_from_catalog(True):\n            # here we do special handling of how set-parameters merge with the yaml header\n            new_context = ControlContext.clone(context)\n\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            set_param_dict: Dict[str, str] = {}\n            for param_id, param_dict in control_param_dict.items():\n                tmp_dict = ModelUtils.parameter_to_dict(param_dict, True)\n                values = tmp_dict.get('values', None)\n                new_dict = {'values': values}\n                set_param_dict[param_id] = new_dict\n            if set_param_dict:\n                if const.SET_PARAMS_TAG not in new_context.cli_yaml_header:\n                    new_context.cli_yaml_header[const.SET_PARAMS_TAG] = {}\n                if new_context.overwrite_header_values:\n                    # update the control params with new values\n                    for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                        if key in control_param_dict:\n                            set_param_dict[key] = value\n                else:\n                    # update the control params with any values in yaml header not set in control\n                    # need to maintain order in the set_param_dict\n                    for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                        if key in control_param_dict and key not in set_param_dict:\n                            set_param_dict[key] = value\n                new_context.cli_yaml_header[const.SET_PARAMS_TAG] = set_param_dict\n            elif const.SET_PARAMS_TAG in new_context.cli_yaml_header:\n                # need to cull any params that are not in control\n                pop_list: List[str] = []\n                for key in new_context.cli_yaml_header[const.SET_PARAMS_TAG].keys():\n                    if key not in control_param_dict:\n                        pop_list.append(key)\n                for pop in pop_list:\n                    new_context.cli_yaml_header[const.SET_PARAMS_TAG].pop(pop)\n\n            self._write_control_into_dir(new_context, control, part_id_map, [])\n\n    def _write_control_into_dir(\n        self,\n        context: ControlContext,\n        control: cat.Control,\n        part_id_map: Dict[str, Dict[str, str]],\n        found_control_alters: List[prof.Alter]\n    ):\n        # we need to create the dir structure on demand because we don't know a priori what groups are included\n        _, group_title, _ = self._catalog_interface.get_group_info_by_control(control.id)\n        group_dir = context.md_root\n        control_path = self._catalog_interface.get_control_path(control.id)\n        for sub_dir in control_path:\n            group_dir = group_dir / sub_dir\n            if not group_dir.exists():\n                group_dir.mkdir(parents=True, exist_ok=True)\n\n        writer = ControlWriter()\n        writer.write_control_for_editing(context, control, group_dir, group_title, part_id_map, found_control_alters)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.__init__","title":"__init__(self, catalog_interface) special","text":"

                                    Initialize catalog writer.

                                    Source code in trestle/core/catalog/catalog_writer.py
                                    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog writer.\"\"\"\n    self._catalog_interface = catalog_interface\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_catalog","title":"write_catalog_as_catalog(self, context, part_id_map)","text":"

                                    Write the catalog as a simple catalog.

                                    Source code in trestle/core/catalog/catalog_writer.py
                                    def write_catalog_as_catalog(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"Write the catalog as a simple catalog.\"\"\"\n    # write out the controls\n    for control in self._catalog_interface.get_all_controls_from_catalog(True):\n        # here we do special handling of how set-parameters merge with the yaml header\n        new_context = ControlContext.clone(context)\n\n        control_param_dict = ControlInterface.get_control_param_dict(control, False)\n        set_param_dict: Dict[str, str] = {}\n        for param_id, param_dict in control_param_dict.items():\n            tmp_dict = ModelUtils.parameter_to_dict(param_dict, True)\n            values = tmp_dict.get('values', None)\n            new_dict = {'values': values}\n            set_param_dict[param_id] = new_dict\n        if set_param_dict:\n            if const.SET_PARAMS_TAG not in new_context.cli_yaml_header:\n                new_context.cli_yaml_header[const.SET_PARAMS_TAG] = {}\n            if new_context.overwrite_header_values:\n                # update the control params with new values\n                for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict:\n                        set_param_dict[key] = value\n            else:\n                # update the control params with any values in yaml header not set in control\n                # need to maintain order in the set_param_dict\n                for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict and key not in set_param_dict:\n                        set_param_dict[key] = value\n            new_context.cli_yaml_header[const.SET_PARAMS_TAG] = set_param_dict\n        elif const.SET_PARAMS_TAG in new_context.cli_yaml_header:\n            # need to cull any params that are not in control\n            pop_list: List[str] = []\n            for key in new_context.cli_yaml_header[const.SET_PARAMS_TAG].keys():\n                if key not in control_param_dict:\n                    pop_list.append(key)\n            for pop in pop_list:\n                new_context.cli_yaml_header[const.SET_PARAMS_TAG].pop(pop)\n\n        self._write_control_into_dir(new_context, control, part_id_map, [])\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_component_markdown","title":"write_catalog_as_component_markdown(self, context, part_id_map)","text":"

                                    Write out the catalog as component markdown.

                                    Source code in trestle/core/catalog/catalog_writer.py
                                    def write_catalog_as_component_markdown(\n    self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]\n) -> None:\n\"\"\"Write out the catalog as component markdown.\"\"\"\n    context.rules_dict = {}\n    context.rules_params_dict = {}\n\n    def _update_values(set_param: comp.SetParameter, control_param_dict) -> None:\n        # set the param values based on the control_param_dict if available\n        if set_param.param_id in control_param_dict:\n            control_param_dict[set_param.param_id] = set_param\n\n    control_ids_in_comp_imp = [\n        imp_req.control_id for imp_req in as_list(context.control_implementation.implemented_requirements)\n    ]\n\n    missing_controls = set(control_ids_in_comp_imp).difference(self._catalog_interface.get_control_ids())\n    if missing_controls:\n        logger.warning(f'Component {context.comp_name} references controls {missing_controls} not in profile.')\n\n    # get top level rule info applying to all controls\n    comp_rules_dict, comp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(context.component)  # noqa E501\n    context.rules_dict[context.comp_name] = comp_rules_dict\n    context.rules_params_dict[context.comp_name] = comp_rules_params_dict\n    for control_imp in as_list(context.component.control_implementations):\n        control_imp_rules_dict, control_imp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)  # noqa E501\n        context.rules_dict[context.comp_name].update(control_imp_rules_dict)\n        comp_rules_params_dict = context.rules_params_dict.get(context.comp_name, {})\n        comp_rules_params_dict.update(control_imp_rules_params_dict)\n        context.rules_params_dict[context.comp_name].update(comp_rules_params_dict)\n        ci_set_params = ControlInterface.get_set_params_from_item(control_imp)\n        for imp_req in as_list(control_imp.implemented_requirements):\n            control_part_id_map = part_id_map.get(imp_req.control_id, {})\n            control_rules, statement_rules, _ = ControlInterface.get_rule_list_for_imp_req(imp_req)\n            if control_rules or statement_rules:\n                if control_rules:\n                    status = ControlInterface.get_status_from_props(imp_req)\n                    comp_info = ComponentImpInfo(imp_req.description, control_rules, [], status)\n                    self._catalog_interface.add_comp_info(imp_req.control_id, context.comp_name, '', comp_info)\n                set_params = copy.deepcopy(ci_set_params)\n                set_params.update(ControlInterface.get_set_params_from_item(imp_req))\n                for set_param in set_params.values():\n                    self._catalog_interface.add_comp_set_param(imp_req.control_id, context.comp_name, set_param)\n                for statement in as_list(imp_req.statements):\n                    rule_list, _ = ControlInterface.get_rule_list_for_item(statement)\n                    if rule_list:\n                        status = ControlInterface.get_status_from_props(statement)\n                        if statement.statement_id not in control_part_id_map:\n                            label = statement.statement_id\n                            logger.warning(\n                                f'No statement label found for statement id {label}.  Defaulting to {label}.'\n                            )\n                        else:\n                            label = control_part_id_map[statement.statement_id]\n                        comp_info = ComponentImpInfo(statement.description, rule_list, [], status)\n                        self._catalog_interface.add_comp_info(\n                            imp_req.control_id, context.comp_name, label, comp_info\n                        )\n\n    catalog_merger = CatalogMerger(self._catalog_interface)\n\n    for control in self._catalog_interface.get_all_controls_from_catalog(True):\n        if control.id in control_ids_in_comp_imp:\n            context.comp_dict = self._catalog_interface.get_comp_info(control.id)\n            new_context = ControlContext.clone(context)\n            # get the resolved catalog values for the control params\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            # update them with values in the ci\n            for set_param in as_list(new_context.control_implementation.set_parameters):\n                _update_values(set_param, control_param_dict)\n            # update them with values in the imp_req\n            for imp_req in as_list(new_context.control_implementation.implemented_requirements):\n                if imp_req.control_id == control.id:\n                    for set_param in as_list(imp_req.set_parameters):\n                        _update_values(set_param, control_param_dict)\n\n            # insert the param values into the header\n            if control_param_dict:\n                new_context.merged_header[const.PARAM_VALUES_TAG] = {}\n                for key, param in control_param_dict.items():\n                    new_context.merged_header[const.PARAM_VALUES_TAG][key] = none_if_empty(\n                        ControlInterface._param_values_as_str_list(param)\n                    )\n            # merge the md_header and md_comp_dict with info in cat_interface for this control\n            control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control.id)\n            catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n            self._write_control_into_dir(new_context, control, part_id_map, [])\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_profile_markdown","title":"write_catalog_as_profile_markdown(self, context, part_id_map, md_alters)","text":"

                                    Write out the catalog as profile markdown.

                                    Source code in trestle/core/catalog/catalog_writer.py
                                    def write_catalog_as_profile_markdown(\n    self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]], md_alters: List[prof.Alter]\n) -> None:\n\"\"\"Write out the catalog as profile markdown.\"\"\"\n    # Get the list of params for this profile from its set_params\n    # this is just from the set_params\n    profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n\n    # write out the controls\n    for control in self._catalog_interface.get_all_controls_from_catalog(True):\n        # here we do special handling of how set-parameters merge with the yaml header\n        new_context = ControlContext.clone(context)\n        new_context.merged_header = {}\n\n        new_context = self._add_inherited_props_to_header(new_context, control.id)\n\n        # get all params and vals for this control from the resolved profile catalog with block adds in effect\n        control_param_dict = ControlInterface.get_control_param_dict(control, False)\n        set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n\n        if set_param_dict:\n            self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n        elif const.SET_PARAMS_TAG in new_context.merged_header:\n            # need to cull any params that are not in control\n            pop_list: List[str] = []\n            for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                if key not in control_param_dict:\n                    pop_list.append(key)\n            for pop in pop_list:\n                new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n        found_control_alters = [alter for alter in md_alters if alter.control_id == control.id]\n\n        self._write_control_into_dir(new_context, control, part_id_map, found_control_alters)\n
                                    "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_ssp_markdown","title":"write_catalog_as_ssp_markdown(self, context, part_id_map)","text":"

                                    Write out the catalog as component markdown.

                                    Already have resolved profile catalog, but with no setparams from compdefs Load all control level rules and param values based on compdefs and profile values

                                    In memory: for each compdef: for each comp: load top level rules for each control_imp: load set-params for each imp_req (bound to 1 control): load set-params load control level rules and status load part level rules and status add as compinfo to control comp_dict

                                    Source code in trestle/core/catalog/catalog_writer.py
                                    def write_catalog_as_ssp_markdown(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"\n    Write out the catalog as component markdown.\n\n    Already have resolved profile catalog, but with no setparams from compdefs\n    Load all control level rules and param values based on compdefs and profile values\n\n    In memory:\n    for each compdef:\n        for each comp:\n            load top level rules\n            for each control_imp:\n                load set-params\n                for each imp_req (bound to 1 control):\n                    load set-params\n                    load control level rules and status\n                    load part level rules and status\n                    add as compinfo to control comp_dict\n\n    \"\"\"\n    # generate rule and param info from the components\n    self._catalog_interface.generate_control_rule_info(part_id_map, context)\n\n    # now have all rules in context.rules_dict and all rules_params in context.rules_params_dict\n    # all set-params per component for each control are in the cat interface\n    # all comp-infos by control and part are in the cat interface\n    #\n    # can now write out catalog and pull from the markdown:\n    # header for param values to set during assem\n    # prose and status for This System\n    # status for all parts that still have rules\n\n    CatalogWriter._fixup_param_dicts(context)\n\n    # remove items left after above loop\n    context.component = None\n    context.comp_name = None\n\n    # get param_dict of set_params in profile\n    profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n    catalog_merger = CatalogMerger(self._catalog_interface)\n    for control in self._catalog_interface.get_all_controls_from_dict():\n        control_id = control.id\n        context.comp_dict = self._catalog_interface._control_comp_dicts.get(control_id, {})\n        control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control_id)\n        control_file_path.parent.mkdir(exist_ok=True, parents=True)\n        # the catalog interface is from the resolved profile catalog\n        control = self._catalog_interface.get_control(control_id)\n        _, group_title, _ = self._catalog_interface.get_group_info_by_control(control_id)\n        control_param_dict = ControlInterface.get_control_param_dict(control, False)\n        set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n        new_context = ControlContext.clone(context)\n\n        if set_param_dict:\n            self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n        elif const.SET_PARAMS_TAG in new_context.merged_header:\n            # need to cull any params that are not in control\n            pop_list: List[str] = []\n            for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                if key not in control_param_dict:\n                    pop_list.append(key)\n            for pop in pop_list:\n                new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n        # merge the md_header and md_comp_dict with info in cat_interface for this control in new_context\n        catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n        if const.COMP_DEF_RULES_PARAM_VALS_TAG in new_context.merged_header:\n            for _, param_list in new_context.merged_header[const.COMP_DEF_RULES_PARAM_VALS_TAG].items():\n                for param_dict in param_list:\n                    param_dict.pop(const.HEADER_RULE_ID, None)\n\n        control_writer = ControlWriter()\n        control_writer.write_control_for_editing(\n            new_context, control, control_file_path.parent, group_title, part_id_map, []\n        )\n
                                    "},{"location":"api_reference/trestle.core.catalog_validator/","title":"catalog_validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator","title":"trestle.core.catalog_validator","text":"

                                    Validate catalog by confirming no duplicate param ids.

                                    "},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.CatalogValidator","title":" CatalogValidator (Validator) ","text":"

                                    Validator to confirm all param ids in catalog are unique.

                                    Source code in trestle/core/catalog_validator.py
                                    class CatalogValidator(Validator):\n\"\"\"Validator to confirm all param ids in catalog are unique.\"\"\"\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if it is not a catalog, or it is a catalog and its links are 1:1 with resources.\n        \"\"\"\n        if not isinstance(model, Catalog):\n            return True\n        catalog: Catalog = model\n        cat_interface = CatalogInterface(catalog)\n        param_ids = set()\n        for control in cat_interface.get_all_controls_from_dict():\n            for param in as_list(control.params):\n                if param.id in param_ids:\n                    logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n                    return False\n                param_ids.add(param.id)\n        for param_id in cat_interface.loose_param_dict.keys():\n            if param_id in param_ids:\n                logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n                return False\n        return True\n
                                    "},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.CatalogValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.CatalogValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                    Test if the model is valid.

                                    Parameters:

                                    Name Type Description Default model ~TopLevelOscalModel

                                    A top level OSCAL model.

                                    required quiet bool

                                    Don't report msgs unless invalid.

                                    required

                                    Returns:

                                    Type Description True (valid) if it is not a catalog, or it is a catalog and its links are 1

                                    1 with resources.

                                    Source code in trestle/core/catalog_validator.py
                                    def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if it is not a catalog, or it is a catalog and its links are 1:1 with resources.\n    \"\"\"\n    if not isinstance(model, Catalog):\n        return True\n    catalog: Catalog = model\n    cat_interface = CatalogInterface(catalog)\n    param_ids = set()\n    for control in cat_interface.get_all_controls_from_dict():\n        for param in as_list(control.params):\n            if param.id in param_ids:\n                logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n                return False\n            param_ids.add(param.id)\n    for param_id in cat_interface.loose_param_dict.keys():\n        if param_id in param_ids:\n            logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n            return False\n    return True\n
                                    "},{"location":"api_reference/trestle.core.commands.add/","title":"add","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add","title":"trestle.core.commands.add","text":"

                                    Trestle Add Command.

                                    "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add","title":" Add ","text":"

                                    Class supporting Add of an OSCAL object to a provided file based on element path.

                                    Examples of element paths: catalog.metadata catalog.controls.control assessment-results.results.

                                    The method first finds the parent model from the file and loads the file into the model. Then the method executes 'add' for each of the element paths specified. Add was originally its own command but has been incorporated into the Create command.

                                    Source code in trestle/core/commands/add.py
                                    class Add():\n\"\"\"\n    Class supporting Add of an OSCAL object to a provided file based on element path.\n\n    Examples of element paths:\n        catalog.metadata\n        catalog.controls.control\n        assessment-results.results.\n\n    The method first finds the parent model from the file and loads the file into the model.\n    Then the method executes 'add' for each of the element paths specified.\n    Add was originally its own command but has been incorporated into the Create command.\n    \"\"\"\n\n    def add_from_args(self, args: argparse.Namespace) -> int:\n\"\"\"Parse args for add element to file.\"\"\"\n        file_path = pathlib.Path(args.file).resolve()\n\n        # Get parent model and then load json into parent model\n        parent_model, _ = ModelUtils.get_stripped_model_type(file_path, args.trestle_root)\n        parent_object = parent_model.oscal_read(file_path)\n        parent_element = Element(parent_object, classname_to_alias(parent_model.__name__, AliasMode.JSON))\n\n        add_plan = Plan()\n        # Do _add for each element_path specified in args\n        element_paths: List[str] = args.element.split(',')\n        for elm_path_str in element_paths:\n            element_path = ElementPath(elm_path_str)\n            update_action, parent_element = self.add(element_path, parent_element, args.include_optional_fields)\n            add_plan.add_action(update_action)\n\n        create_action = CreatePathAction(file_path, True)\n        # this will output json or yaml based on type of input file\n        write_action = WriteFileAction(file_path, parent_element, FileContentType.to_content_type(file_path.suffix))\n\n        add_plan.add_action(create_action)\n        add_plan.add_action(write_action)\n\n        add_plan.execute()\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def add(element_path: ElementPath, parent_element: Element, include_optional: bool) -> Tuple[UpdateAction, Element]:\n\"\"\"For a element_path, add a child model to the parent_element of a given parent_model.\n\n        Args:\n            element_path: element path of the item to create within the model\n            parent_element: the parent element that will host the created element\n            include_optional: whether to create optional attributes in the created element\n\n        Notes:\n            First we find the child model at the specified element path and instantiate it with default values.\n            Then we check if there's already existing element at that path, in which case we append the child model\n            to the existing list of dict.\n            Then we set up an action plan to update the model (specified by file_path) in memory, create a file\n            at the same location and write the file.\n            We update the parent_element to prepare for next adds in the chain\n        \"\"\"\n        if '*' in element_path.get_full_path_parts():\n            raise err.TrestleError('trestle add does not support Wildcard element path.')\n        # Get child model\n        try:\n            child_model = element_path.get_type(type(parent_element.get()))\n\n            # Create child element with sample values\n            child_object = gens.generate_sample_model(child_model, include_optional=include_optional)\n\n            if parent_element.get_at(element_path) is not None:\n                # The element already exists\n                if type(parent_element.get_at(element_path)) is list:\n                    child_object = parent_element.get_at(element_path) + child_object\n                elif type(parent_element.get_at(element_path)) is dict:\n                    child_object = {**parent_element.get_at(element_path), **child_object}\n                else:\n                    raise err.TrestleError('Already exists and is not a list or dictionary.')\n\n        except Exception as e:\n            raise err.TrestleError(f'Bad element path. {str(e)}')\n\n        update_action = UpdateAction(\n            sub_element=child_object, dest_element=parent_element, sub_element_path=element_path\n        )\n        parent_element = parent_element.set_at(element_path, child_object)\n\n        return update_action, parent_element\n
                                    "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add.add","title":"add(element_path, parent_element, include_optional) staticmethod","text":"

                                    For a element_path, add a child model to the parent_element of a given parent_model.

                                    Parameters:

                                    Name Type Description Default element_path ElementPath

                                    element path of the item to create within the model

                                    required parent_element Element

                                    the parent element that will host the created element

                                    required include_optional bool

                                    whether to create optional attributes in the created element

                                    required

                                    Notes

                                    First we find the child model at the specified element path and instantiate it with default values. Then we check if there's already existing element at that path, in which case we append the child model to the existing list of dict. Then we set up an action plan to update the model (specified by file_path) in memory, create a file at the same location and write the file. We update the parent_element to prepare for next adds in the chain

                                    Source code in trestle/core/commands/add.py
                                    @staticmethod\ndef add(element_path: ElementPath, parent_element: Element, include_optional: bool) -> Tuple[UpdateAction, Element]:\n\"\"\"For a element_path, add a child model to the parent_element of a given parent_model.\n\n    Args:\n        element_path: element path of the item to create within the model\n        parent_element: the parent element that will host the created element\n        include_optional: whether to create optional attributes in the created element\n\n    Notes:\n        First we find the child model at the specified element path and instantiate it with default values.\n        Then we check if there's already existing element at that path, in which case we append the child model\n        to the existing list of dict.\n        Then we set up an action plan to update the model (specified by file_path) in memory, create a file\n        at the same location and write the file.\n        We update the parent_element to prepare for next adds in the chain\n    \"\"\"\n    if '*' in element_path.get_full_path_parts():\n        raise err.TrestleError('trestle add does not support Wildcard element path.')\n    # Get child model\n    try:\n        child_model = element_path.get_type(type(parent_element.get()))\n\n        # Create child element with sample values\n        child_object = gens.generate_sample_model(child_model, include_optional=include_optional)\n\n        if parent_element.get_at(element_path) is not None:\n            # The element already exists\n            if type(parent_element.get_at(element_path)) is list:\n                child_object = parent_element.get_at(element_path) + child_object\n            elif type(parent_element.get_at(element_path)) is dict:\n                child_object = {**parent_element.get_at(element_path), **child_object}\n            else:\n                raise err.TrestleError('Already exists and is not a list or dictionary.')\n\n    except Exception as e:\n        raise err.TrestleError(f'Bad element path. {str(e)}')\n\n    update_action = UpdateAction(\n        sub_element=child_object, dest_element=parent_element, sub_element_path=element_path\n    )\n    parent_element = parent_element.set_at(element_path, child_object)\n\n    return update_action, parent_element\n
                                    "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add.add_from_args","title":"add_from_args(self, args)","text":"

                                    Parse args for add element to file.

                                    Source code in trestle/core/commands/add.py
                                    def add_from_args(self, args: argparse.Namespace) -> int:\n\"\"\"Parse args for add element to file.\"\"\"\n    file_path = pathlib.Path(args.file).resolve()\n\n    # Get parent model and then load json into parent model\n    parent_model, _ = ModelUtils.get_stripped_model_type(file_path, args.trestle_root)\n    parent_object = parent_model.oscal_read(file_path)\n    parent_element = Element(parent_object, classname_to_alias(parent_model.__name__, AliasMode.JSON))\n\n    add_plan = Plan()\n    # Do _add for each element_path specified in args\n    element_paths: List[str] = args.element.split(',')\n    for elm_path_str in element_paths:\n        element_path = ElementPath(elm_path_str)\n        update_action, parent_element = self.add(element_path, parent_element, args.include_optional_fields)\n        add_plan.add_action(update_action)\n\n    create_action = CreatePathAction(file_path, True)\n    # this will output json or yaml based on type of input file\n    write_action = WriteFileAction(file_path, parent_element, FileContentType.to_content_type(file_path.suffix))\n\n    add_plan.add_action(create_action)\n    add_plan.add_action(write_action)\n\n    add_plan.execute()\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.assemble/","title":"assemble","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble","title":"trestle.core.commands.assemble","text":"

                                    Trestle Assemble Command.

                                    "},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd","title":" AssembleCmd (CommandPlusDocs) ","text":"

                                    Assemble all subcomponents from a specified trestle model into a single JSON/YAML file under dist.

                                    Source code in trestle/core/commands/assemble.py
                                    class AssembleCmd(CommandPlusDocs):\n\"\"\"Assemble all subcomponents from a specified trestle model into a single JSON/YAML file under dist.\"\"\"\n\n    name = 'assemble'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('model', help='', choices=const.MODEL_TYPE_LIST)\n        self.add_argument('-n', '--name', help='Name of a single model to assemble.')\n        self.add_argument('-t', '--type', action='store_true', help='Assemble all models of the given type.')\n        self.add_argument(\n            '-x', '--extension', help='Type of file output.', choices=['json', 'yaml', 'yml'], default='json'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            return self.assemble_model(args.model, args)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while assembling OSCAL model')\n\n    @classmethod\n    def assemble_model(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"Assemble a top level OSCAL model within the trestle dist directory.\"\"\"\n        log.set_log_level_from_args(args)\n        logger.info(f'Assembling models of type {model_alias}.')\n\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n        if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n            raise TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n        model_names = []\n        if args.name:\n            model_names = [args.name]\n            logger.info(f'Assembling single model of type {model_alias}: {args.name}.')\n        else:\n            model_names = ModelUtils.get_models_of_type(model_alias, trestle_root)\n            nmodels = len(model_names)\n            logger.info(f'Assembling {nmodels} found models of type {model_alias}.')\n        if len(model_names) == 0:\n            logger.info(f'No models found to assemble of type {model_alias}.')\n            return CmdReturnCodes.SUCCESS.value\n\n        for model_name in model_names:\n            # contruct path to the model file name\n            root_model_dir = trestle_root / ModelUtils.model_type_to_model_dir(model_alias)\n\n            model_file_type = file_utils.get_contextual_file_type(root_model_dir / model_name)\n\n            model_file_name = f'{model_alias}{FileContentType.to_file_extension(model_file_type)}'\n            root_model_filepath = root_model_dir / model_name / model_file_name\n\n            if not root_model_filepath.exists():\n                raise TrestleError(f'No top level model file at {root_model_dir}')\n\n            assembled_model = load_validate_model_path(args.trestle_root, root_model_filepath)\n            plural_alias = ModelUtils.model_type_to_model_dir(model_alias)\n\n            assembled_model_dir = trestle_root / const.TRESTLE_DIST_DIR / plural_alias\n\n            assembled_model_filepath = assembled_model_dir / f'{model_name}.{args.extension}'\n\n            plan = Plan()\n            plan.add_action(CreatePathAction(assembled_model_filepath, True))\n            plan.add_action(\n                WriteFileAction(\n                    assembled_model_filepath,\n                    Element(assembled_model),\n                    FileContentType.to_content_type(f'.{args.extension}')\n                )\n            )\n\n            plan.execute()\n\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd.assemble_model","title":"assemble_model(model_alias, args) classmethod","text":"

                                    Assemble a top level OSCAL model within the trestle dist directory.

                                    Source code in trestle/core/commands/assemble.py
                                    @classmethod\ndef assemble_model(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"Assemble a top level OSCAL model within the trestle dist directory.\"\"\"\n    log.set_log_level_from_args(args)\n    logger.info(f'Assembling models of type {model_alias}.')\n\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n    if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n        raise TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n    model_names = []\n    if args.name:\n        model_names = [args.name]\n        logger.info(f'Assembling single model of type {model_alias}: {args.name}.')\n    else:\n        model_names = ModelUtils.get_models_of_type(model_alias, trestle_root)\n        nmodels = len(model_names)\n        logger.info(f'Assembling {nmodels} found models of type {model_alias}.')\n    if len(model_names) == 0:\n        logger.info(f'No models found to assemble of type {model_alias}.')\n        return CmdReturnCodes.SUCCESS.value\n\n    for model_name in model_names:\n        # contruct path to the model file name\n        root_model_dir = trestle_root / ModelUtils.model_type_to_model_dir(model_alias)\n\n        model_file_type = file_utils.get_contextual_file_type(root_model_dir / model_name)\n\n        model_file_name = f'{model_alias}{FileContentType.to_file_extension(model_file_type)}'\n        root_model_filepath = root_model_dir / model_name / model_file_name\n\n        if not root_model_filepath.exists():\n            raise TrestleError(f'No top level model file at {root_model_dir}')\n\n        assembled_model = load_validate_model_path(args.trestle_root, root_model_filepath)\n        plural_alias = ModelUtils.model_type_to_model_dir(model_alias)\n\n        assembled_model_dir = trestle_root / const.TRESTLE_DIST_DIR / plural_alias\n\n        assembled_model_filepath = assembled_model_dir / f'{model_name}.{args.extension}'\n\n        plan = Plan()\n        plan.add_action(CreatePathAction(assembled_model_filepath, True))\n        plan.add_action(\n            WriteFileAction(\n                assembled_model_filepath,\n                Element(assembled_model),\n                FileContentType.to_content_type(f'.{args.extension}')\n            )\n        )\n\n        plan.execute()\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.catalog/","title":"catalog","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog","title":"trestle.core.commands.author.catalog","text":"

                                    Author commands to generate catalog controls as markdown and assemble them back to json.

                                    "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble","title":" CatalogAssemble (AuthorCommonCommand) ","text":"

                                    Assemble markdown files of controls into a Catalog json file.

                                    Source code in trestle/core/commands/author/catalog.py
                                    class CatalogAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into a Catalog json file.\"\"\"\n\n    name = 'catalog-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the catalog model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the input markdown file directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json Catalog'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-sp', '--set-parameters', action='store_true', help=const.HELP_SET_PARAMS)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n            return CatalogAssemble.assemble_catalog(\n                trestle_root=trestle_root,\n                md_name=args.markdown,\n                assem_cat_name=args.output,\n                parent_cat_name=args.name,\n                set_parameters_flag=args.set_parameters,\n                regenerate=args.regenerate,\n                version=args.version\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred while assembling catalog')\n\n    @staticmethod\n    def assemble_catalog(\n        trestle_root: pathlib.Path,\n        md_name: str,\n        assem_cat_name: str,\n        parent_cat_name: Optional[str],\n        set_parameters_flag: bool,\n        regenerate: bool,\n        version: Optional[str]\n    ) -> int:\n\"\"\"\n        Assemble the markdown directory into a json catalog model file.\n\n        Args:\n            trestle_root: The trestle root directory\n            md_name: The name of the directory containing the markdown control files for the ssp\n            assem_cat_name: The output name of the catalog model to be created from the assembly\n            parent_cat_name: Optional name of the parent catalog that the markdown controls will replace\n            set_parameters_flag: set the parameters and props in the control to the values in the markdown yaml header\n            regenerate: whether to regenerate the uuid's in the catalog\n            version: version for the assembled catalog\n\n        Returns:\n            0 on success, 1 otherwise\n\n        Notes:\n            If the destination catalog_name model already exists in the trestle workspace, it is overwritten.\n            If a parent catalog is not specified, the assembled catalog will be used as the parent if it exists.\n            If no parent catalog name is available, the catalog is created anew using only the markdown content.\n        \"\"\"\n        md_dir = trestle_root / md_name\n        if not md_dir.exists():\n            raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n        # assemble the markdown controls into fresh md_catalog\n        catalog_api_from_md = CatalogAPI(catalog=None)\n        try:\n            md_catalog = catalog_api_from_md.read_catalog_from_markdown(md_dir, set_parameters_flag)\n        except Exception as e:\n            raise TrestleError(f'Error reading catalog from markdown {md_dir}: {e}')\n\n        # this is None if it doesn't exist yet\n        assem_cat_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, assem_cat_name, Catalog)\n        logger.debug(f'assem_cat_path is {assem_cat_path}')\n\n        # if original cat is not specified, use the assembled cat but only if it already exists\n        if not parent_cat_name and assem_cat_path:\n            parent_cat_name = assem_cat_name\n\n        # default to JSON but allow override later if other file type found\n        new_content_type = FileContentType.JSON\n\n        # if we have parent catalog then merge the markdown controls into it\n        # the parent can be a separate catalog or the destination assembled catalog if it exists\n        # but this is the catalog that the markdown is merged into in memory\n        logger.debug(f'parent_cat_name is {parent_cat_name}')\n        if parent_cat_name:\n            parent_cat, parent_cat_path = load_validate_model_name(trestle_root, parent_cat_name, Catalog)\n            parent_cat_api = CatalogAPI(catalog=parent_cat)\n            # merge the just-read md catalog into the original json\n            parent_cat_api.merge_catalog(md_catalog, set_parameters_flag)\n            md_catalog = parent_cat_api._catalog_interface.get_catalog()\n            new_content_type = FileContentType.path_to_content_type(parent_cat_path)\n\n        if version:\n            md_catalog.metadata.version = version\n\n        # now check the destination catalog to see if the in-memory catalog matches it\n        if assem_cat_path:\n            new_content_type = FileContentType.path_to_content_type(assem_cat_path)\n            existing_cat = load_validate_model_path(trestle_root, assem_cat_path)\n            if ModelUtils.models_are_equivalent(existing_cat, md_catalog):  # type: ignore\n                logger.info('Assembled catalog is not different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n            else:\n                logger.debug('new assembled catalog is different from existing one')\n\n        if regenerate:\n            md_catalog, _, _ = ModelUtils.regenerate_uuids(md_catalog)\n            logger.debug('regenerating uuids in catalog')\n        ModelUtils.update_last_modified(md_catalog)\n\n        md_catalog.metadata.oscal_version = OSCAL_VERSION\n\n        # we still may not know the assem_cat_path but can now create it with file content type\n        assem_cat_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, assem_cat_name, Catalog, new_content_type\n        )\n\n        if assem_cat_path.parent.exists():\n            logger.info('Creating catalog from markdown and destination catalog exists, so updating.')\n            shutil.rmtree(str(assem_cat_path.parent))\n\n        assem_cat_path.parent.mkdir(parents=True, exist_ok=True)\n        md_catalog.oscal_write(assem_cat_path.parent / 'catalog.json')\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble.assemble_catalog","title":"assemble_catalog(trestle_root, md_name, assem_cat_name, parent_cat_name, set_parameters_flag, regenerate, version) staticmethod","text":"

                                    Assemble the markdown directory into a json catalog model file.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    The trestle root directory

                                    required md_name str

                                    The name of the directory containing the markdown control files for the ssp

                                    required assem_cat_name str

                                    The output name of the catalog model to be created from the assembly

                                    required parent_cat_name Optional[str]

                                    Optional name of the parent catalog that the markdown controls will replace

                                    required set_parameters_flag bool

                                    set the parameters and props in the control to the values in the markdown yaml header

                                    required regenerate bool

                                    whether to regenerate the uuid's in the catalog

                                    required version Optional[str]

                                    version for the assembled catalog

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success, 1 otherwise

                                    Notes

                                    If the destination catalog_name model already exists in the trestle workspace, it is overwritten. If a parent catalog is not specified, the assembled catalog will be used as the parent if it exists. If no parent catalog name is available, the catalog is created anew using only the markdown content.

                                    Source code in trestle/core/commands/author/catalog.py
                                    @staticmethod\ndef assemble_catalog(\n    trestle_root: pathlib.Path,\n    md_name: str,\n    assem_cat_name: str,\n    parent_cat_name: Optional[str],\n    set_parameters_flag: bool,\n    regenerate: bool,\n    version: Optional[str]\n) -> int:\n\"\"\"\n    Assemble the markdown directory into a json catalog model file.\n\n    Args:\n        trestle_root: The trestle root directory\n        md_name: The name of the directory containing the markdown control files for the ssp\n        assem_cat_name: The output name of the catalog model to be created from the assembly\n        parent_cat_name: Optional name of the parent catalog that the markdown controls will replace\n        set_parameters_flag: set the parameters and props in the control to the values in the markdown yaml header\n        regenerate: whether to regenerate the uuid's in the catalog\n        version: version for the assembled catalog\n\n    Returns:\n        0 on success, 1 otherwise\n\n    Notes:\n        If the destination catalog_name model already exists in the trestle workspace, it is overwritten.\n        If a parent catalog is not specified, the assembled catalog will be used as the parent if it exists.\n        If no parent catalog name is available, the catalog is created anew using only the markdown content.\n    \"\"\"\n    md_dir = trestle_root / md_name\n    if not md_dir.exists():\n        raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n    # assemble the markdown controls into fresh md_catalog\n    catalog_api_from_md = CatalogAPI(catalog=None)\n    try:\n        md_catalog = catalog_api_from_md.read_catalog_from_markdown(md_dir, set_parameters_flag)\n    except Exception as e:\n        raise TrestleError(f'Error reading catalog from markdown {md_dir}: {e}')\n\n    # this is None if it doesn't exist yet\n    assem_cat_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, assem_cat_name, Catalog)\n    logger.debug(f'assem_cat_path is {assem_cat_path}')\n\n    # if original cat is not specified, use the assembled cat but only if it already exists\n    if not parent_cat_name and assem_cat_path:\n        parent_cat_name = assem_cat_name\n\n    # default to JSON but allow override later if other file type found\n    new_content_type = FileContentType.JSON\n\n    # if we have parent catalog then merge the markdown controls into it\n    # the parent can be a separate catalog or the destination assembled catalog if it exists\n    # but this is the catalog that the markdown is merged into in memory\n    logger.debug(f'parent_cat_name is {parent_cat_name}')\n    if parent_cat_name:\n        parent_cat, parent_cat_path = load_validate_model_name(trestle_root, parent_cat_name, Catalog)\n        parent_cat_api = CatalogAPI(catalog=parent_cat)\n        # merge the just-read md catalog into the original json\n        parent_cat_api.merge_catalog(md_catalog, set_parameters_flag)\n        md_catalog = parent_cat_api._catalog_interface.get_catalog()\n        new_content_type = FileContentType.path_to_content_type(parent_cat_path)\n\n    if version:\n        md_catalog.metadata.version = version\n\n    # now check the destination catalog to see if the in-memory catalog matches it\n    if assem_cat_path:\n        new_content_type = FileContentType.path_to_content_type(assem_cat_path)\n        existing_cat = load_validate_model_path(trestle_root, assem_cat_path)\n        if ModelUtils.models_are_equivalent(existing_cat, md_catalog):  # type: ignore\n            logger.info('Assembled catalog is not different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n        else:\n            logger.debug('new assembled catalog is different from existing one')\n\n    if regenerate:\n        md_catalog, _, _ = ModelUtils.regenerate_uuids(md_catalog)\n        logger.debug('regenerating uuids in catalog')\n    ModelUtils.update_last_modified(md_catalog)\n\n    md_catalog.metadata.oscal_version = OSCAL_VERSION\n\n    # we still may not know the assem_cat_path but can now create it with file content type\n    assem_cat_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, assem_cat_name, Catalog, new_content_type\n    )\n\n    if assem_cat_path.parent.exists():\n        logger.info('Creating catalog from markdown and destination catalog exists, so updating.')\n        shutil.rmtree(str(assem_cat_path.parent))\n\n    assem_cat_path.parent.mkdir(parents=True, exist_ok=True)\n    md_catalog.oscal_write(assem_cat_path.parent / 'catalog.json')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate","title":" CatalogGenerate (AuthorCommonCommand) ","text":"

                                    Generate Catalog controls in markdown form from a catalog in the trestle workspace.

                                    Source code in trestle/core/commands/author/catalog.py
                                    class CatalogGenerate(AuthorCommonCommand):\n\"\"\"Generate Catalog controls in markdown form from a catalog in the trestle workspace.\"\"\"\n\n    name = 'catalog-generate'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the catalog model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument(\n            '-o', '--output', help='Name of the output generated catalog markdown folder', required=True, type=str\n        )  # noqa E501\n        self.add_argument('-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true')\n        self.add_argument('-y', '--yaml-header', help=const.HELP_YAML_PATH, required=False, type=str)\n        self.add_argument(\n            '-ohv',\n            '--overwrite-header-values',\n            help=const.HELP_OVERWRITE_HEADER_VALUES,\n            required=False,\n            action='store_true',\n            default=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = args.trestle_root\n            if not file_utils.is_directory_name_allowed(args.output):\n                raise TrestleError(f'{args.output} is not an allowed directory name')\n\n            if args.force_overwrite:\n                try:\n                    logger.info(f'Overwriting the content in {args.output} folder.')\n                    clear_folder(pathlib.Path(args.output))\n                except TrestleError as e:  # pragma: no cover\n                    raise TrestleError(f'Unable to overwrite contents in {args.output} folder: {e}')\n\n            yaml_header: Dict[str, Any] = {}\n            if args.yaml_header:\n                try:\n                    logging.debug(f'Loading yaml header file {args.yaml_header}')\n                    yaml = YAML(typ='safe')\n                    yaml_header = yaml.load(pathlib.Path(args.yaml_header).open('r'))\n                except YAMLError as e:\n                    raise TrestleError(f'YAML error loading yaml header {args.yaml_header} for ssp generation: {e}')\n\n            catalog_path = trestle_root / f'catalogs/{args.name}/catalog.json'\n\n            markdown_path = trestle_root / args.output\n\n            return self.generate_markdown(\n                trestle_root, catalog_path, markdown_path, yaml_header, args.overwrite_header_values\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when generating markdown for catalog')\n\n    def generate_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        catalog_path: pathlib.Path,\n        markdown_path: pathlib.Path,\n        yaml_header: Dict[str, Any],\n        overwrite_header_values: bool\n    ) -> int:\n\"\"\"Generate markdown for the controls in the catalog.\"\"\"\n        try:\n            catalog = load_validate_model_path(trestle_root, catalog_path)\n            context = ControlContext.generate(\n                ContextPurpose.CATALOG,\n                True,\n                trestle_root,\n                markdown_path,\n                cli_yaml_header=yaml_header,\n                overwrite_header_values=overwrite_header_values,\n                set_parameters_flag=True\n            )\n            catalog_api = CatalogAPI(catalog=catalog, context=context)\n            catalog_api.write_catalog_as_markdown()\n\n        except TrestleNotFoundError as e:\n            raise TrestleError(f'Catalog {catalog_path} not found for load: {e}')\n        except Exception as e:\n            raise TrestleError(f'Error generating markdown for controls in {catalog_path}: {e}')\n\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate.generate_markdown","title":"generate_markdown(self, trestle_root, catalog_path, markdown_path, yaml_header, overwrite_header_values)","text":"

                                    Generate markdown for the controls in the catalog.

                                    Source code in trestle/core/commands/author/catalog.py
                                    def generate_markdown(\n    self,\n    trestle_root: pathlib.Path,\n    catalog_path: pathlib.Path,\n    markdown_path: pathlib.Path,\n    yaml_header: Dict[str, Any],\n    overwrite_header_values: bool\n) -> int:\n\"\"\"Generate markdown for the controls in the catalog.\"\"\"\n    try:\n        catalog = load_validate_model_path(trestle_root, catalog_path)\n        context = ControlContext.generate(\n            ContextPurpose.CATALOG,\n            True,\n            trestle_root,\n            markdown_path,\n            cli_yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            set_parameters_flag=True\n        )\n        catalog_api = CatalogAPI(catalog=catalog, context=context)\n        catalog_api.write_catalog_as_markdown()\n\n    except TrestleNotFoundError as e:\n        raise TrestleError(f'Catalog {catalog_path} not found for load: {e}')\n    except Exception as e:\n        raise TrestleError(f'Error generating markdown for controls in {catalog_path}: {e}')\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.command/","title":"command","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command","title":"trestle.core.commands.author.command","text":"

                                    Trestle author command.

                                    Umbrella command for all markdown related transformations

                                    "},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.AuthorCmd","title":" AuthorCmd (CommandPlusDocs) ","text":"

                                    trestle author, a collection of commands for authoring compliance content outside of OSCAL.

                                    Source code in trestle/core/commands/author/command.py
                                    class AuthorCmd(CommandPlusDocs):\n\"\"\"trestle author, a collection of commands for authoring compliance content outside of OSCAL.\"\"\"\n\n    name = 'author'\n\n    subcommands = [\n        CatalogAssemble,\n        CatalogGenerate,\n        ComponentAssemble,\n        ComponentGenerate,\n        Docs,\n        Folders,\n        Headers,\n        JinjaCmd,\n        ProfileAssemble,\n        ProfileGenerate,\n        ProfileInherit,\n        ProfileResolve,\n        SSPAssemble,\n        SSPFilter,\n        SSPGenerate\n    ]\n
                                    "},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.AuthorCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.AuthorCmd.subcommands","title":"subcommands","text":""},{"location":"api_reference/trestle.core.commands.author.common/","title":"common","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common","title":"trestle.core.commands.author.common","text":"

                                    AuthorCommonCommands - reusable utilities to increase code base abstraction for author command.

                                    "},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.AuthorCommonCommand","title":" AuthorCommonCommand (CommandPlusDocs) ","text":"

                                    Extension for the subset of commands that operate using the common mode structure.

                                    Source code in trestle/core/commands/author/common.py
                                    class AuthorCommonCommand(CommandPlusDocs):\n\"\"\"Extension for the subset of commands that operate using the common mode structure.\"\"\"\n\n    trestle_root: pathlib.Path\n\n    task_name: str\n\n    def _initialize(self, args: argparse.Namespace) -> int:\n        log.set_log_level_from_args(args)\n        # Externalize\n        self.trestle_root = args.trestle_root\n        self.task_name = args.task_name\n\n        try:\n            self.global_ = args.__getattribute__('global')\n        except AttributeError:\n            self.global_ = None\n\n        if self.task_name:\n            self.task_path = self.trestle_root / self.task_name\n            if not file_utils.is_directory_name_allowed(self.task_name):\n                logger.error(\n                    f'Task name {self.task_name} is invalid as it interferes with OSCAL and trestle reserved names.'\n                )\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n        rc = self._setup_template_dir(args)\n\n        return rc\n\n    def rel_dir(self, path: pathlib.Path) -> str:\n\"\"\"Stringify a directory relative to trestle root.\"\"\"\n        return str(path.relative_to(self.trestle_root))\n\n    def _setup_template_dir(self, args: argparse.Namespace) -> int:\n\"\"\"Set template directory and update to new format.\"\"\"\n        if not self.global_ and self.task_name is None:\n            logger.error('At least a global flag or a task name should be provided.')\n            return CmdReturnCodes.INCORRECT_ARGS.value\n        if self.global_:\n            old_template_dir = self.trestle_root / TRESTLE_CONFIG_DIR / 'author' / '__global__'\n            self._set_template_version_to_latest(args, old_template_dir)\n            self.template_dir = old_template_dir / args.template_version\n        elif self.task_name and not self.global_:\n            old_template_dir = self.trestle_root / TRESTLE_CONFIG_DIR / 'author' / self.task_name\n            self._set_template_version_to_latest(args, old_template_dir)\n            self.template_dir = old_template_dir / args.template_version\n\n        if old_template_dir.exists():\n            TemplateVersioning.update_template_folder_structure(old_template_dir)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    def _set_template_version_to_latest(self, args: argparse.Namespace, template_dir: pathlib.Path) -> None:\n\"\"\"Set template version argument to the latest version if none was given.\"\"\"\n        if not TemplateVersioning.is_valid_version(args.template_version):\n            raise TrestleError(f'Version {args.template_version} is invalid, version format should be: 0.0.1')\n        if args.template_version is None and args.mode == ARG_VALIDATE:\n            # in validate mode no version will validate instances based on header version\n            args.template_version = ''\n        if args.template_version is None:\n            args.template_version = START_TEMPLATE_VERSION\n            if template_dir.exists():\n                all_versions = TemplateVersioning.get_all_versions_for_task(template_dir)\n                if all_versions:\n                    args.template_version = max(all_versions)\n        if args.template_version == '':\n            logger.info('Instances will be validated against template version specified in their headers.')\n        else:\n            logger.info(f'Set template version to {args.template_version}.')\n
                                    "},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.AuthorCommonCommand-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.AuthorCommonCommand.rel_dir","title":"rel_dir(self, path)","text":"

                                    Stringify a directory relative to trestle root.

                                    Source code in trestle/core/commands/author/common.py
                                    def rel_dir(self, path: pathlib.Path) -> str:\n\"\"\"Stringify a directory relative to trestle root.\"\"\"\n    return str(path.relative_to(self.trestle_root))\n
                                    "},{"location":"api_reference/trestle.core.commands.author.component/","title":"component","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component","title":"trestle.core.commands.author.component","text":"

                                    Author commands to generate component definition as markdown and assemble to json after edit.

                                    "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble","title":" ComponentAssemble (AuthorCommonCommand) ","text":"

                                    Assemble markdown files of controls into a Component json file.

                                    Source code in trestle/core/commands/author/component.py
                                    class ComponentAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into a Component json file.\"\"\"\n\n    name = 'component-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the component-definition model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the source markdown directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json component-definition (ok to overwrite original)'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            return self.assemble_component(\n                trestle_root=args.trestle_root,\n                parent_comp_name=args.name,\n                md_name=args.markdown,\n                assem_comp_name=args.output,\n                regenerate=args.regenerate,\n                version=args.version,\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Assembly of markdown to component-definition failed')\n\n    @staticmethod\n    def assemble_component(\n        trestle_root: pathlib.Path,\n        parent_comp_name: Optional[str],\n        md_name: str,\n        assem_comp_name: str,\n        regenerate: bool,\n        version: Optional[str],\n    ) -> int:\n\"\"\"\n        Assemble the markdown directory into a json component-definition model file.\n\n        Args:\n            trestle_root: The trestle root directory\n            parent_comp_name: Optional name of component-definition used to generate markdown, default = assem_comp_name\n            md_name: The name of the directory containing the markdown control files for the component\n            assem_comp_name: The name of the assembled component-definiton.  Can be same as the parent to overwrite\n            regenerate: Whether to regenerate the uuid's in the component\n            version: Optional version for the assembled component\n\n        Returns:\n            0 on success, 1 otherwise\n\n        Notes:\n            There must already be a component model and it will either be updated or a new json component created.\n            The generated markdown has the current values for parameters of controls being imported, as set by\n            the original catalog and any intermediate components.  It also shows the current SetParameters being applied\n            by this component.  That list of SetParameters can be edited by changing the assigned values and adding or\n            removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n            in the assembled component if the --set-parameters option is specified.\n        \"\"\"\n        md_dir = trestle_root / md_name\n        if not md_dir.exists():\n            raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n        if not parent_comp_name:\n            parent_comp_name = assem_comp_name\n\n        # load the comp-def that will be updated\n        parent_comp, parent_comp_path = ModelUtils.load_model_for_class(\n            trestle_root,\n            parent_comp_name,\n            comp.ComponentDefinition\n        )\n        new_content_type = FileContentType.path_to_content_type(parent_comp_path)\n\n        context = ControlContext.generate(ContextPurpose.COMPONENT, False, trestle_root, md_dir)\n\n        ComponentAssemble.assemble_comp_def_into_parent(parent_comp, md_dir, context)\n\n        if version:\n            parent_comp.metadata.version = version\n\n        assem_comp_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, assem_comp_name, comp.ComponentDefinition, new_content_type\n        )\n\n        if not version and assem_comp_path.exists():\n            _, _, existing_comp = ModelUtils.load_distributed(assem_comp_path, trestle_root)\n            # comp def will change statement uuids so need to ignore them in comparison\n            if ModelUtils.models_are_equivalent(existing_comp, parent_comp, True):  # type: ignore\n                logger.info('Assembled component definition is no different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n\n        if regenerate:\n            parent_comp, _, _ = ModelUtils.regenerate_uuids(parent_comp)\n        ModelUtils.update_last_modified(parent_comp)  # type: ignore\n\n        if assem_comp_path.parent.exists():\n            logger.info(\n                'Creating component definition from markdown and destination component definition exists, so updating.'\n            )  # noqa E501\n            shutil.rmtree(str(assem_comp_path.parent))\n\n        assem_comp_path.parent.mkdir(parents=True, exist_ok=True)\n        parent_comp.oscal_write(assem_comp_path)  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def assemble_comp_def_into_parent(\n        parent_comp: comp.ComponentDefinition, md_dir: pathlib.Path, context: ControlContext\n    ) -> None:\n\"\"\"Assemble markdown content into provided component-definition model.\"\"\"\n        # find the needed list of comps\n        sub_dirs = file_utils.iterdir_without_hidden_files(md_dir)\n        comp_names = [sub_dir.name for sub_dir in sub_dirs if sub_dir.is_dir()]\n\n        # make sure parent has list of comps to work with - possibly empty\n        if not parent_comp.components:\n            parent_comp.components = []\n\n        parent_comp.components[:] = [comp for comp in parent_comp.components if comp.title in comp_names]\n\n        # create new comps if needed\n        existing_comp_names = [component.title for component in parent_comp.components]\n        for comp_name in comp_names:\n            if comp_name not in existing_comp_names:\n                parent_comp.components.append(\n                    comp.DefinedComponent(\n                        uuid=str(uuid4()), title=comp_name, type=const.REPLACE_ME, description=const.REPLACE_ME\n                    )\n                )\n\n        for component in parent_comp.components:\n            context.comp_name = component.title\n            context.comp_def = parent_comp\n            context.component = component\n            logger.info(f'Assembling markdown for component {component.title}')\n            ComponentAssemble._update_component_with_markdown(md_dir, component, context)\n\n    @staticmethod\n    def _get_profile_title_and_href_from_dir(md_dir: pathlib.Path) -> Tuple[str, str]:\n\"\"\"Get profile title and href from yaml header of first md file found in dir that has info.\"\"\"\n        md_files = md_dir.rglob('*.md')\n        markdown_api = MarkdownAPI()\n        for md_file in md_files:\n            header, _ = markdown_api.processor.read_markdown_wo_processing(md_file)\n            prof_title = deep_get(header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.TITLE])\n            profile_href = deep_get(header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.HREF], 'unknown_href')\n            # return first one found\n            if prof_title:\n                return prof_title, profile_href\n        logger.warning(f'Cannot find profile title and href in markdown headers of directory {md_dir}')\n        return 'unknown_title', 'unknown_href'\n\n    @staticmethod\n    def _update_component_with_markdown(\n        md_dir: pathlib.Path, component: comp.DefinedComponent, context: ControlContext\n    ) -> None:\n        md_path = md_dir / component.title\n        sub_dirs = file_utils.iterdir_without_hidden_files(md_path)\n        source_dirs = [sub_dir.name for sub_dir in sub_dirs if sub_dir.is_dir()]\n        for source_dir in source_dirs:\n            profile_title, _ = ComponentAssemble._get_profile_title_and_href_from_dir(md_path / source_dir)\n            # context has defined component and comp_name\n            imp_reqs = CatalogReader.read_catalog_imp_reqs(md_path / source_dir, context)\n            # the imp_reqs need to be inserted into the correct control_implementation\n            for imp_req in imp_reqs:\n                ControlInterface.insert_imp_req_into_component(component, imp_req, profile_title, context.trestle_root)\n
                                    "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble.assemble_comp_def_into_parent","title":"assemble_comp_def_into_parent(parent_comp, md_dir, context) staticmethod","text":"

                                    Assemble markdown content into provided component-definition model.

                                    Source code in trestle/core/commands/author/component.py
                                    @staticmethod\ndef assemble_comp_def_into_parent(\n    parent_comp: comp.ComponentDefinition, md_dir: pathlib.Path, context: ControlContext\n) -> None:\n\"\"\"Assemble markdown content into provided component-definition model.\"\"\"\n    # find the needed list of comps\n    sub_dirs = file_utils.iterdir_without_hidden_files(md_dir)\n    comp_names = [sub_dir.name for sub_dir in sub_dirs if sub_dir.is_dir()]\n\n    # make sure parent has list of comps to work with - possibly empty\n    if not parent_comp.components:\n        parent_comp.components = []\n\n    parent_comp.components[:] = [comp for comp in parent_comp.components if comp.title in comp_names]\n\n    # create new comps if needed\n    existing_comp_names = [component.title for component in parent_comp.components]\n    for comp_name in comp_names:\n        if comp_name not in existing_comp_names:\n            parent_comp.components.append(\n                comp.DefinedComponent(\n                    uuid=str(uuid4()), title=comp_name, type=const.REPLACE_ME, description=const.REPLACE_ME\n                )\n            )\n\n    for component in parent_comp.components:\n        context.comp_name = component.title\n        context.comp_def = parent_comp\n        context.component = component\n        logger.info(f'Assembling markdown for component {component.title}')\n        ComponentAssemble._update_component_with_markdown(md_dir, component, context)\n
                                    "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble.assemble_component","title":"assemble_component(trestle_root, parent_comp_name, md_name, assem_comp_name, regenerate, version) staticmethod","text":"

                                    Assemble the markdown directory into a json component-definition model file.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    The trestle root directory

                                    required parent_comp_name Optional[str]

                                    Optional name of component-definition used to generate markdown, default = assem_comp_name

                                    required md_name str

                                    The name of the directory containing the markdown control files for the component

                                    required assem_comp_name str

                                    The name of the assembled component-definiton. Can be same as the parent to overwrite

                                    required regenerate bool

                                    Whether to regenerate the uuid's in the component

                                    required version Optional[str]

                                    Optional version for the assembled component

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success, 1 otherwise

                                    Notes

                                    There must already be a component model and it will either be updated or a new json component created. The generated markdown has the current values for parameters of controls being imported, as set by the original catalog and any intermediate components. It also shows the current SetParameters being applied by this component. That list of SetParameters can be edited by changing the assigned values and adding or removing SetParameters from that list. During assembly that list will be used to create the SetParameters in the assembled component if the --set-parameters option is specified.

                                    Source code in trestle/core/commands/author/component.py
                                    @staticmethod\ndef assemble_component(\n    trestle_root: pathlib.Path,\n    parent_comp_name: Optional[str],\n    md_name: str,\n    assem_comp_name: str,\n    regenerate: bool,\n    version: Optional[str],\n) -> int:\n\"\"\"\n    Assemble the markdown directory into a json component-definition model file.\n\n    Args:\n        trestle_root: The trestle root directory\n        parent_comp_name: Optional name of component-definition used to generate markdown, default = assem_comp_name\n        md_name: The name of the directory containing the markdown control files for the component\n        assem_comp_name: The name of the assembled component-definiton.  Can be same as the parent to overwrite\n        regenerate: Whether to regenerate the uuid's in the component\n        version: Optional version for the assembled component\n\n    Returns:\n        0 on success, 1 otherwise\n\n    Notes:\n        There must already be a component model and it will either be updated or a new json component created.\n        The generated markdown has the current values for parameters of controls being imported, as set by\n        the original catalog and any intermediate components.  It also shows the current SetParameters being applied\n        by this component.  That list of SetParameters can be edited by changing the assigned values and adding or\n        removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n        in the assembled component if the --set-parameters option is specified.\n    \"\"\"\n    md_dir = trestle_root / md_name\n    if not md_dir.exists():\n        raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n    if not parent_comp_name:\n        parent_comp_name = assem_comp_name\n\n    # load the comp-def that will be updated\n    parent_comp, parent_comp_path = ModelUtils.load_model_for_class(\n        trestle_root,\n        parent_comp_name,\n        comp.ComponentDefinition\n    )\n    new_content_type = FileContentType.path_to_content_type(parent_comp_path)\n\n    context = ControlContext.generate(ContextPurpose.COMPONENT, False, trestle_root, md_dir)\n\n    ComponentAssemble.assemble_comp_def_into_parent(parent_comp, md_dir, context)\n\n    if version:\n        parent_comp.metadata.version = version\n\n    assem_comp_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, assem_comp_name, comp.ComponentDefinition, new_content_type\n    )\n\n    if not version and assem_comp_path.exists():\n        _, _, existing_comp = ModelUtils.load_distributed(assem_comp_path, trestle_root)\n        # comp def will change statement uuids so need to ignore them in comparison\n        if ModelUtils.models_are_equivalent(existing_comp, parent_comp, True):  # type: ignore\n            logger.info('Assembled component definition is no different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n\n    if regenerate:\n        parent_comp, _, _ = ModelUtils.regenerate_uuids(parent_comp)\n    ModelUtils.update_last_modified(parent_comp)  # type: ignore\n\n    if assem_comp_path.parent.exists():\n        logger.info(\n            'Creating component definition from markdown and destination component definition exists, so updating.'\n        )  # noqa E501\n        shutil.rmtree(str(assem_comp_path.parent))\n\n    assem_comp_path.parent.mkdir(parents=True, exist_ok=True)\n    parent_comp.oscal_write(assem_comp_path)  # type: ignore\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate","title":" ComponentGenerate (AuthorCommonCommand) ","text":"

                                    Generate component in markdown form from a component in the trestle workspace.

                                    Source code in trestle/core/commands/author/component.py
                                    class ComponentGenerate(AuthorCommonCommand):\n\"\"\"Generate component in markdown form from a component in the trestle workspace.\"\"\"\n\n    name = 'component-generate'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the source component model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument(\n            '-o', '--output', help='Name of the output generated component markdown folder', required=True, type=str\n        )  # noqa E501\n        self.add_argument('-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true')\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n\n            if args.force_overwrite:\n                try:\n                    logger.info(f'Overwriting the content in {args.output} folder.')\n                    clear_folder(pathlib.Path(args.output))\n                except TrestleError as e:  # pragma: no cover\n                    raise TrestleError(f'Unable to overwrite contents in {args.output} folder: {e}')\n\n            return self.component_generate_all(args.trestle_root, args.name, args.output)\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Generation of the component markdown failed')\n\n    def component_generate_all(self, trestle_root: pathlib.Path, comp_def_name: str, markdown_dir_name: str) -> int:\n\"\"\"Generate markdown for all components in comp def.\"\"\"\n        if not file_utils.is_directory_name_allowed(markdown_dir_name):\n            raise TrestleError(f'{markdown_dir_name} is not an allowed directory name')\n        md_path = trestle_root / markdown_dir_name\n        md_path.mkdir(parents=True, exist_ok=True)\n        component_def, _ = load_validate_model_name(trestle_root, comp_def_name, comp.ComponentDefinition)\n\n        context = ControlContext.generate(ContextPurpose.COMPONENT, True, trestle_root, md_path)\n        context.prompt_responses = True\n        context.comp_def = component_def\n\n        rc = CmdReturnCodes.SUCCESS.value\n        for component in as_list(component_def.components):\n            rc = self.component_generate_by_name(context, component, md_path / component.title)\n            if rc != CmdReturnCodes.SUCCESS.value:\n                break\n        return rc\n\n    @staticmethod\n    def _get_name_from_uri(source_uri: str) -> str:\n\"\"\"Get the name from a source profile or catalog source uri.\"\"\"\n        uri_type = FetcherFactory.get_uri_type(source_uri)\n        if uri_type == FetcherFactory.UriType.TRESTLE:\n            return source_uri.split('/')[-2]\n        return ''\n\n    def component_generate_by_name(\n        self, context: ControlContext, component: comp.DefinedComponent, markdown_dir_path: pathlib.Path\n    ) -> int:\n\"\"\"Create markdown for the component using its source profiles.\"\"\"\n        logger.info(f'Generating markdown for component {component.title}')\n        context.comp_name = component.title\n        context.component = component\n        context.uri_name_map = {}\n        cat_api_dict: Dict[str, CatalogAPI] = {}\n        name_index = 1\n        for control_imp in as_list(component.control_implementations):\n            context.control_implementation = control_imp\n            source_profile_uri = control_imp.source\n            # get the resolved profile catalog for this source, generating it if not already created\n            if source_profile_uri not in cat_api_dict:\n                name = ComponentGenerate._get_name_from_uri(source_profile_uri)\n                if not name:\n                    name = f'source_{name_index:03d}'\n                    name_index += 1\n                context.uri_name_map[source_profile_uri] = name\n                resolved_catalog = ProfileResolver.get_resolved_profile_catalog(\n                    context.trestle_root, source_profile_uri, param_rep=ParameterRep.LEAVE_MOUSTACHE\n                )\n                local_catalog_api = CatalogAPI(resolved_catalog)\n                cat_api_dict[source_profile_uri] = local_catalog_api\n            else:\n                local_catalog_api = cat_api_dict[source_profile_uri]\n            # insert the profile title (from title of resolved catalog) into the yaml header so it appears in md\n            # different controls in the final catalog may have different profile titles if from different control_imps\n            context.cli_yaml_header = {}\n            context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG] = {}\n\n            profile_title = local_catalog_api._catalog_interface.get_catalog_title()\n            profile_header = {'title': profile_title, 'href': source_profile_uri}\n            context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG][const.PROFILE] = profile_header\n\n            sub_dir_name = context.uri_name_map[source_profile_uri]\n            context.md_root = markdown_dir_path / sub_dir_name\n            # write controls corresponding to this source catalog\n            # if two controlimps load the same control, the second one will merge into the first\n            # otherwise the full catalog will be written in subsets by control_imp\n            # if an imp_req has a set param also in the control_imp. the imp_req value is used for the control\n            cat_api_dict[source_profile_uri].update_context(context)\n            cat_api_dict[source_profile_uri].write_catalog_as_markdown()\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate.component_generate_all","title":"component_generate_all(self, trestle_root, comp_def_name, markdown_dir_name)","text":"

                                    Generate markdown for all components in comp def.

                                    Source code in trestle/core/commands/author/component.py
                                    def component_generate_all(self, trestle_root: pathlib.Path, comp_def_name: str, markdown_dir_name: str) -> int:\n\"\"\"Generate markdown for all components in comp def.\"\"\"\n    if not file_utils.is_directory_name_allowed(markdown_dir_name):\n        raise TrestleError(f'{markdown_dir_name} is not an allowed directory name')\n    md_path = trestle_root / markdown_dir_name\n    md_path.mkdir(parents=True, exist_ok=True)\n    component_def, _ = load_validate_model_name(trestle_root, comp_def_name, comp.ComponentDefinition)\n\n    context = ControlContext.generate(ContextPurpose.COMPONENT, True, trestle_root, md_path)\n    context.prompt_responses = True\n    context.comp_def = component_def\n\n    rc = CmdReturnCodes.SUCCESS.value\n    for component in as_list(component_def.components):\n        rc = self.component_generate_by_name(context, component, md_path / component.title)\n        if rc != CmdReturnCodes.SUCCESS.value:\n            break\n    return rc\n
                                    "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate.component_generate_by_name","title":"component_generate_by_name(self, context, component, markdown_dir_path)","text":"

                                    Create markdown for the component using its source profiles.

                                    Source code in trestle/core/commands/author/component.py
                                    def component_generate_by_name(\n    self, context: ControlContext, component: comp.DefinedComponent, markdown_dir_path: pathlib.Path\n) -> int:\n\"\"\"Create markdown for the component using its source profiles.\"\"\"\n    logger.info(f'Generating markdown for component {component.title}')\n    context.comp_name = component.title\n    context.component = component\n    context.uri_name_map = {}\n    cat_api_dict: Dict[str, CatalogAPI] = {}\n    name_index = 1\n    for control_imp in as_list(component.control_implementations):\n        context.control_implementation = control_imp\n        source_profile_uri = control_imp.source\n        # get the resolved profile catalog for this source, generating it if not already created\n        if source_profile_uri not in cat_api_dict:\n            name = ComponentGenerate._get_name_from_uri(source_profile_uri)\n            if not name:\n                name = f'source_{name_index:03d}'\n                name_index += 1\n            context.uri_name_map[source_profile_uri] = name\n            resolved_catalog = ProfileResolver.get_resolved_profile_catalog(\n                context.trestle_root, source_profile_uri, param_rep=ParameterRep.LEAVE_MOUSTACHE\n            )\n            local_catalog_api = CatalogAPI(resolved_catalog)\n            cat_api_dict[source_profile_uri] = local_catalog_api\n        else:\n            local_catalog_api = cat_api_dict[source_profile_uri]\n        # insert the profile title (from title of resolved catalog) into the yaml header so it appears in md\n        # different controls in the final catalog may have different profile titles if from different control_imps\n        context.cli_yaml_header = {}\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG] = {}\n\n        profile_title = local_catalog_api._catalog_interface.get_catalog_title()\n        profile_header = {'title': profile_title, 'href': source_profile_uri}\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG][const.PROFILE] = profile_header\n\n        sub_dir_name = context.uri_name_map[source_profile_uri]\n        context.md_root = markdown_dir_path / sub_dir_name\n        # write controls corresponding to this source catalog\n        # if two controlimps load the same control, the second one will merge into the first\n        # otherwise the full catalog will be written in subsets by control_imp\n        # if an imp_req has a set param also in the control_imp. the imp_req value is used for the control\n        cat_api_dict[source_profile_uri].update_context(context)\n        cat_api_dict[source_profile_uri].write_catalog_as_markdown()\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.consts/","title":"consts","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts","title":"trestle.core.commands.author.consts","text":"

                                    Constants associated with trestle author commands to decrease duplication.

                                    "},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.EXCLUDE_HELP","title":"EXCLUDE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.EXCLUDE_LONG","title":"EXCLUDE_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.EXCLUDE_SHORT","title":"EXCLUDE_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GH_HELP","title":"GH_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GH_LONG","title":"GH_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GH_SHORT","title":"GH_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GLOBAL_HELP","title":"GLOBAL_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GLOBAL_LONG","title":"GLOBAL_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GLOBAL_SHORT","title":"GLOBAL_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HEADER_VALIDATE_HELP","title":"HEADER_VALIDATE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HOV_HELP","title":"HOV_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HOV_LONG","title":"HOV_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HOV_SHORT","title":"HOV_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.IGNORE_HELP","title":"IGNORE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_HEADER_VALIDATE","title":"LONG_HEADER_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_IGNORE","title":"LONG_IGNORE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_README_VALIDATE","title":"LONG_README_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_TEMPLATE_VERSION","title":"LONG_TEMPLATE_VERSION","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.MODE_ARG_NAME","title":"MODE_ARG_NAME","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.MODE_CHOICES","title":"MODE_CHOICES","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.README_VALIDATE_FOLDERS_HELP","title":"README_VALIDATE_FOLDERS_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.README_VALIDATE_HELP","title":"README_VALIDATE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.RECURSE_HELP","title":"RECURSE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.RECURSE_LONG","title":"RECURSE_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.RECURSE_SHORT","title":"RECURSE_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.REFERENCE_TEMPLATES","title":"REFERENCE_TEMPLATES","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_HEADER_VALIDATE","title":"SHORT_HEADER_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_IGNORE","title":"SHORT_IGNORE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_README_VALIDATE","title":"SHORT_README_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_TEMPLATE_VERSION","title":"SHORT_TEMPLATE_VERSION","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.START_TEMPLATE_VERSION","title":"START_TEMPLATE_VERSION","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TASK_NAME_LONG","title":"TASK_NAME_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TASK_NAME_SHORT","title":"TASK_NAME_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_HEADER","title":"TEMPLATE_TYPE_HEADER","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_VALIDATE_HELP","title":"TEMPLATE_TYPE_VALIDATE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_VALIDATE_LONG","title":"TEMPLATE_TYPE_VALIDATE_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_VALIDATE_SHORT","title":"TEMPLATE_TYPE_VALIDATE_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_VERSION_HEADER","title":"TEMPLATE_VERSION_HEADER","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_VERSION_HELP","title":"TEMPLATE_VERSION_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TRESTLE_RESOURCES","title":"TRESTLE_RESOURCES","text":""},{"location":"api_reference/trestle.core.commands.author.docs/","title":"docs","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs","title":"trestle.core.commands.author.docs","text":"

                                    Trestle author docs sub-command.

                                    "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs","title":" Docs (AuthorCommonCommand) ","text":"

                                    Markdown governed documents - enforcing consistent markdown across a set of files.

                                    Source code in trestle/core/commands/author/docs.py
                                    class Docs(AuthorCommonCommand):\n\"\"\"Markdown governed documents - enforcing consistent markdown across a set of files.\"\"\"\n\n    name = 'docs'\n\n    template_name = 'template.md'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            author_const.GH_SHORT, author_const.GH_LONG, help=author_const.GH_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_HEADER_VALIDATE,\n            author_const.LONG_HEADER_VALIDATE,\n            help=author_const.HEADER_VALIDATE_HELP,\n            action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_TEMPLATE_VERSION,\n            author_const.LONG_TEMPLATE_VERSION,\n            help=author_const.TEMPLATE_VERSION_HELP,\n            action='store'\n        )\n        self.add_argument(\n            author_const.HOV_SHORT, author_const.HOV_LONG, help=author_const.HOV_HELP, action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_IGNORE, author_const.LONG_IGNORE, help=author_const.IGNORE_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.RECURSE_SHORT, author_const.RECURSE_LONG, help=author_const.RECURSE_HELP, action='store_true'\n        )\n        self.add_argument(author_const.MODE_ARG_NAME, choices=author_const.MODE_CHOICES)\n        tn_help_str = '\\n'.join(\n            [\n                'The name of the the task to be governed.',\n                ''\n                'The template file is at .trestle/author/[task-name]/template.md',\n                'Note that by default this will automatically enforce the task.'\n            ]\n        )\n\n        self.add_argument(\n            author_const.TASK_NAME_SHORT, author_const.TASK_NAME_LONG, help=tn_help_str, required=True, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_README_VALIDATE,\n            author_const.LONG_README_VALIDATE,\n            help=author_const.README_VALIDATE_HELP,\n            action='store_true'\n        )\n\n        self.add_argument(\n            author_const.TEMPLATE_TYPE_VALIDATE_SHORT,\n            author_const.TEMPLATE_TYPE_VALIDATE_LONG,\n            help=author_const.TEMPLATE_TYPE_VALIDATE_HELP,\n            action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            status = 1\n            if self._initialize(args):\n                return status\n\n            if args.mode == 'create-sample':\n                status = self.create_sample()\n\n            elif args.mode == 'template-validate':\n                status = self.template_validate(\n                    args.governed_heading,\n                    args.header_validate,\n                    args.header_only_validate,\n                )\n            elif args.mode == 'setup':\n                status = self.setup_template_governed_docs(args.template_version)\n            elif args.mode == 'validate':\n                # mode is validate\n                status = self.validate(\n                    args.governed_heading,\n                    args.header_validate,\n                    args.header_only_validate,\n                    args.recurse,\n                    args.readme_validate,\n                    args.template_version,\n                    args.ignore,\n                    args.validate_template_type\n                )\n\n            return status\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle author docs')\n\n    def setup_template_governed_docs(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\n\n        Returns:\n            Unix return code.\n        \"\"\"\n        if not self.task_path.exists():\n            self.task_path.mkdir(exist_ok=True, parents=True)\n        elif self.task_path.is_file():\n            raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n        if not self.template_dir.exists():\n            self.template_dir.mkdir(exist_ok=True, parents=True)\n        elif self.template_dir.is_file():\n            raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n        logger.debug(self.template_dir)\n        if not self._validate_template_dir():\n            raise TrestleError('Aborting setup')\n        template_file = self.template_dir / self.template_name\n        if template_file.is_file():\n            return CmdReturnCodes.SUCCESS.value\n        TemplateVersioning.write_versioned_template('template.md', self.template_dir, template_file, template_version)\n        logger.info(f'Template file setup for task {self.task_name} at {self.rel_dir(template_file)}')\n        logger.info(f'Task directory is {self.rel_dir(self.task_path)}')\n        return CmdReturnCodes.SUCCESS.value\n\n    def create_sample(self) -> int:\n\"\"\"Presuming the template exists, copy into a sample markdown file with an index.\"\"\"\n        template_file = self.template_dir / self.template_name\n\n        if not self._validate_template_dir():\n            raise TrestleError('Aborting setup')\n        if not template_file.is_file():\n            raise TrestleError('No template file ... exiting.')\n\n        index = 0\n        while True:\n            candidate_task = self.task_path / f'{self.task_name}_{index:03d}.md'\n            if candidate_task.is_file():\n                index = index + 1\n            else:\n                shutil.copy(str(template_file), str(candidate_task))\n                break\n        return CmdReturnCodes.SUCCESS.value\n\n    def template_validate(self, heading: Optional[str], validate_header: bool, validate_only_header: bool) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n        template_file = self.template_dir / self.template_name\n        if not self._validate_template_dir():\n            raise TrestleError(f'Aborting setup, template directory {self.template_dir} is invalid.')\n        if not template_file.is_file():\n            raise TrestleError(f'Required template file: {self.rel_dir(template_file)} does not exist. Exiting.')\n        try:\n            md_api = MarkdownAPI()\n            validate_body = False if validate_only_header else True\n            md_api.load_validator_with_template(\n                template_file, validate_header or validate_only_header, validate_body, heading, True\n            )\n        except Exception as ex:\n            raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n        logger.info(f'TEMPLATES VALID: {self.task_name}')\n        return CmdReturnCodes.SUCCESS.value\n\n    def _validate_template_dir(self) -> bool:\n\"\"\"Template directory should only have template file.\"\"\"\n        for child in file_utils.iterdir_without_hidden_files(self.template_dir):\n            # Only allowable template file in the directory is the template directory.\n            if child.name != self.template_name and child.name.lower() != 'readme.md':\n                logger.warning(f'Unknown file: {child.name} in template directory {self.rel_dir(self.template_dir)}')\n                return False\n        return True\n\n    def _validate_dir(\n        self,\n        governed_heading: str,\n        md_dir: pathlib.Path,\n        validate_header: bool,\n        validate_only_header: bool,\n        recurse: bool,\n        readme_validate: bool,\n        template_version: Optional[str] = None,\n        ignore: Optional[str] = None,\n        validate_by_type_field: bool = False\n    ) -> int:\n\"\"\"\n        Validate md files in a directory with option to recurse.\n\n        Template version will be fetched from the instance header.\n        \"\"\"\n        # status is a linux returncode\n        status = 0\n        for item_path in md_dir.iterdir():\n            if file_utils.is_local_and_visible(item_path):\n                if item_path.is_file():\n                    if not item_path.suffix == const.MARKDOWN_FILE_EXT:\n                        logger.info(\n                            f'Unexpected file {self.rel_dir(item_path)} in folder {self.rel_dir(md_dir)}, skipping.'\n                        )\n                        continue\n                    if not readme_validate and item_path.name.lower() == 'readme.md':\n                        continue\n\n                    if ignore:\n                        p = re.compile(ignore)\n                        matched = p.match(item_path.parts[-1])\n                        if matched is not None:\n                            logger.info(f'Ignoring file {item_path} from validation.')\n                            continue\n\n                    md_api = MarkdownAPI()\n                    if template_version != '':\n                        template_file = self.template_dir / self.template_name\n                    else:\n                        instance_version = md_api.processor.fetch_value_from_header(\n                            item_path, author_const.TEMPLATE_VERSION_HEADER\n                        )\n                        if instance_version is None:\n                            instance_version = '0.0.1'\n                        versione_template_dir = TemplateVersioning.get_versioned_template_dir(\n                            self.template_dir, instance_version\n                        )\n                        # checks on naming template name out of type header if needed\n                        if validate_by_type_field:\n                            # get template name out of its type which essentially needs to be the same\n                            template_name = md_api.processor.fetch_value_from_header(\n                                item_path, author_const.TEMPLATE_TYPE_HEADER\n                            )\n                            # throw an error if template type is not present\n                            if template_name is None:\n                                logger.error(\n                                    f'INVALID: Instance file {item_path} does not have'\n                                    f' {author_const.TEMPLATE_TYPE_HEADER}'\n                                    ' field in its header and can not be validated using optional parameter validate'\n                                    ' template type field'\n                                )\n                                status = 1\n                                return status\n                            template_name = template_name + '.md'\n                            template_file = versione_template_dir / template_name\n                        else:  # continues regular flow without template type\n                            template_file = versione_template_dir / self.template_name\n                    if not template_file.is_file():\n                        raise TrestleError(\n                            f'Required template file: {self.rel_dir(template_file)} does not exist. Exiting.'\n                        )\n                    md_api.load_validator_with_template(\n                        template_file, validate_header, not validate_only_header, governed_heading\n                    )\n                    if not md_api.validate_instance(item_path):\n                        logger.info(f'INVALID: {self.rel_dir(item_path)}')\n                        status = 1\n                    else:\n                        logger.info(f'VALID: {self.rel_dir(item_path)}')\n                elif recurse:\n                    if ignore:\n                        p = re.compile(ignore)\n                        if len(list(filter(p.match, str(item_path.relative_to(md_dir)).split('/')))) > 0:\n                            logger.info(f'Ignoring directory {item_path} from validation.')\n                            continue\n                    rc = self._validate_dir(\n                        governed_heading,\n                        item_path,\n                        validate_header,\n                        validate_only_header,\n                        recurse,\n                        readme_validate,\n                        template_version,\n                        ignore,\n                        validate_by_type_field\n                    )\n                    if rc != 0:\n                        status = rc\n\n        return status\n\n    def validate(\n        self,\n        governed_heading: str,\n        validate_header: bool,\n        validate_only_header: bool,\n        recurse: bool,\n        readme_validate: bool,\n        template_version: str,\n        ignore: str,\n        validate_by_type_field: bool\n    ) -> int:\n\"\"\"\n        Validate task.\n\n        Args:\n            governed_heading: A heading for which structural enforcement (see online docs).\n            validate_header: Whether or not to validate the key structure of the yaml header to the markdown document.\n            validate_only_header: Whether to validate just the yaml header.\n            recurse: Whether to allow validated files to be in a directory tree.\n            readme_validate: Whether to validate readme files, otherwise they will be ignored.\n\n        Returns:\n            Return code to be used for the command.\n        \"\"\"\n        if not self.task_path.is_dir():\n            raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n        return self._validate_dir(\n            governed_heading,\n            self.task_path,\n            validate_header,\n            validate_only_header,\n            recurse,\n            readme_validate,\n            template_version,\n            ignore,\n            validate_by_type_field\n        )\n
                                    "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.template_name","title":"template_name","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.create_sample","title":"create_sample(self)","text":"

                                    Presuming the template exists, copy into a sample markdown file with an index.

                                    Source code in trestle/core/commands/author/docs.py
                                    def create_sample(self) -> int:\n\"\"\"Presuming the template exists, copy into a sample markdown file with an index.\"\"\"\n    template_file = self.template_dir / self.template_name\n\n    if not self._validate_template_dir():\n        raise TrestleError('Aborting setup')\n    if not template_file.is_file():\n        raise TrestleError('No template file ... exiting.')\n\n    index = 0\n    while True:\n        candidate_task = self.task_path / f'{self.task_name}_{index:03d}.md'\n        if candidate_task.is_file():\n            index = index + 1\n        else:\n            shutil.copy(str(template_file), str(candidate_task))\n            break\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.setup_template_governed_docs","title":"setup_template_governed_docs(self, template_version)","text":"

                                    Create structure to allow markdown template enforcement.

                                    Returns:

                                    Type Description int

                                    Unix return code.

                                    Source code in trestle/core/commands/author/docs.py
                                    def setup_template_governed_docs(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\n\n    Returns:\n        Unix return code.\n    \"\"\"\n    if not self.task_path.exists():\n        self.task_path.mkdir(exist_ok=True, parents=True)\n    elif self.task_path.is_file():\n        raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n    if not self.template_dir.exists():\n        self.template_dir.mkdir(exist_ok=True, parents=True)\n    elif self.template_dir.is_file():\n        raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n    logger.debug(self.template_dir)\n    if not self._validate_template_dir():\n        raise TrestleError('Aborting setup')\n    template_file = self.template_dir / self.template_name\n    if template_file.is_file():\n        return CmdReturnCodes.SUCCESS.value\n    TemplateVersioning.write_versioned_template('template.md', self.template_dir, template_file, template_version)\n    logger.info(f'Template file setup for task {self.task_name} at {self.rel_dir(template_file)}')\n    logger.info(f'Task directory is {self.rel_dir(self.task_path)}')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.template_validate","title":"template_validate(self, heading, validate_header, validate_only_header)","text":"

                                    Validate that the template is acceptable markdown.

                                    Source code in trestle/core/commands/author/docs.py
                                    def template_validate(self, heading: Optional[str], validate_header: bool, validate_only_header: bool) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n    template_file = self.template_dir / self.template_name\n    if not self._validate_template_dir():\n        raise TrestleError(f'Aborting setup, template directory {self.template_dir} is invalid.')\n    if not template_file.is_file():\n        raise TrestleError(f'Required template file: {self.rel_dir(template_file)} does not exist. Exiting.')\n    try:\n        md_api = MarkdownAPI()\n        validate_body = False if validate_only_header else True\n        md_api.load_validator_with_template(\n            template_file, validate_header or validate_only_header, validate_body, heading, True\n        )\n    except Exception as ex:\n        raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n    logger.info(f'TEMPLATES VALID: {self.task_name}')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.validate","title":"validate(self, governed_heading, validate_header, validate_only_header, recurse, readme_validate, template_version, ignore, validate_by_type_field)","text":"

                                    Validate task.

                                    Parameters:

                                    Name Type Description Default governed_heading str

                                    A heading for which structural enforcement (see online docs).

                                    required validate_header bool

                                    Whether or not to validate the key structure of the yaml header to the markdown document.

                                    required validate_only_header bool

                                    Whether to validate just the yaml header.

                                    required recurse bool

                                    Whether to allow validated files to be in a directory tree.

                                    required readme_validate bool

                                    Whether to validate readme files, otherwise they will be ignored.

                                    required

                                    Returns:

                                    Type Description int

                                    Return code to be used for the command.

                                    Source code in trestle/core/commands/author/docs.py
                                    def validate(\n    self,\n    governed_heading: str,\n    validate_header: bool,\n    validate_only_header: bool,\n    recurse: bool,\n    readme_validate: bool,\n    template_version: str,\n    ignore: str,\n    validate_by_type_field: bool\n) -> int:\n\"\"\"\n    Validate task.\n\n    Args:\n        governed_heading: A heading for which structural enforcement (see online docs).\n        validate_header: Whether or not to validate the key structure of the yaml header to the markdown document.\n        validate_only_header: Whether to validate just the yaml header.\n        recurse: Whether to allow validated files to be in a directory tree.\n        readme_validate: Whether to validate readme files, otherwise they will be ignored.\n\n    Returns:\n        Return code to be used for the command.\n    \"\"\"\n    if not self.task_path.is_dir():\n        raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n    return self._validate_dir(\n        governed_heading,\n        self.task_path,\n        validate_header,\n        validate_only_header,\n        recurse,\n        readme_validate,\n        template_version,\n        ignore,\n        validate_by_type_field\n    )\n
                                    "},{"location":"api_reference/trestle.core.commands.author.folders/","title":"folders","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders","title":"trestle.core.commands.author.folders","text":"

                                    Trestle author docs sub-command.

                                    "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders","title":" Folders (AuthorCommonCommand) ","text":"

                                    Markdown governed folders - enforcing consistent files and templates across directories.

                                    Source code in trestle/core/commands/author/folders.py
                                    class Folders(AuthorCommonCommand):\n\"\"\"Markdown governed folders - enforcing consistent files and templates across directories.\"\"\"\n\n    name = 'folders'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            author_const.GH_SHORT, author_const.GH_LONG, help=author_const.GH_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_HEADER_VALIDATE,\n            author_const.LONG_HEADER_VALIDATE,\n            help=author_const.HEADER_VALIDATE_HELP,\n            action='store_true'\n        )\n        self.add_argument(\n            author_const.HOV_SHORT, author_const.HOV_LONG, help=author_const.HOV_HELP, action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_TEMPLATE_VERSION,\n            author_const.LONG_TEMPLATE_VERSION,\n            help=author_const.TEMPLATE_VERSION_HELP,\n            action='store'\n        )\n        self.add_argument(\n            author_const.SHORT_IGNORE, author_const.LONG_IGNORE, help=author_const.IGNORE_HELP, default=None, type=str\n        )\n        self.add_argument(author_const.MODE_ARG_NAME, choices=author_const.MODE_CHOICES)\n        tn_help_str = '\\n'.join(\n            [\n                'The name of the the task to be governed.',\n                '',\n                'The template files are at .trestle/author/[task-name],',\n                'where the directory tree established and the markdown files within that directory'\n                + 'tree are enforced.'\n            ]\n        )\n\n        self.add_argument(\n            author_const.TASK_NAME_SHORT, author_const.TASK_NAME_LONG, help=tn_help_str, required=True, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_README_VALIDATE,\n            author_const.LONG_README_VALIDATE,\n            help=author_const.README_VALIDATE_FOLDERS_HELP,\n            action='store_true'\n        )\n\n        self.add_argument(\n            author_const.TEMPLATE_TYPE_VALIDATE_SHORT,\n            author_const.TEMPLATE_TYPE_VALIDATE_LONG,\n            help=author_const.TEMPLATE_TYPE_VALIDATE_HELP,\n            action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            if self._initialize(args):\n                raise TrestleError(f'Error when initializing trestle folders command with args: {args}')\n            if args.mode == 'create-sample':\n                status = self.create_sample()\n\n            elif args.mode == 'template-validate':\n                status = self.template_validate(\n                    args.header_validate, args.header_only_validate, args.governed_heading, args.readme_validate\n                )\n            elif args.mode == 'setup':\n                status = self.setup_template(args.template_version)\n            elif args.mode == 'validate':\n                # mode is validate\n                status = self.validate(\n                    args.header_validate,\n                    args.header_only_validate,\n                    args.governed_heading,\n                    args.readme_validate,\n                    args.template_version,\n                    args.ignore,\n                    args.validate_template_type\n                )\n            else:\n                raise TrestleIncorrectArgsError(f'Unsupported mode: {args.mode} for folders command.')\n\n            return status\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle author folders')\n\n    def setup_template(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\"\"\"\n        if not self.task_path.exists():\n            self.task_path.mkdir(exist_ok=True, parents=True)\n        elif self.task_path.is_file():\n            raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n        if not self.template_dir.exists():\n            self.template_dir.mkdir(exist_ok=True, parents=True)\n        elif self.template_dir.is_file():\n            raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n\n        template_file_a_md = self.template_dir / 'a_template.md'\n        template_file_another_md = self.template_dir / 'another_template.md'\n        template_file_drawio = self.template_dir / 'architecture.drawio'\n        TemplateVersioning.write_versioned_template(\n            'template.md', self.template_dir, template_file_a_md, template_version\n        )\n        TemplateVersioning.write_versioned_template(\n            'template.md', self.template_dir, template_file_another_md, template_version\n        )\n        TemplateVersioning.write_versioned_template(\n            'template.drawio', self.template_dir, template_file_drawio, template_version\n        )\n\n        return CmdReturnCodes.SUCCESS.value\n\n    def template_validate(\n        self, validate_header: bool, validate_only_header: bool, heading: str, readme_validate: bool\n    ) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n        if not self.template_dir.is_dir():\n            raise TrestleError(\n                f'Template directory {self.rel_dir(self.template_dir)} for task {self.task_name} does not exist.'\n            )\n        # get list of files:\n        template_files = self.template_dir.rglob('*')\n\n        for template_file in template_files:\n            try:\n                if not file_utils.is_local_and_visible(template_file):\n                    continue\n                elif template_file.is_dir():\n                    continue\n                elif template_file.suffix.lower() == const.MARKDOWN_FILE_EXT:\n                    if not readme_validate and template_file.name == 'readme.md':\n                        raise TrestleError('Template directory contains a readme.md file and readme validation is off.')\n\n                    md_api = MarkdownAPI()\n                    md_api.load_validator_with_template(\n                        template_file, validate_header, not validate_only_header, heading\n                    )\n                elif template_file.suffix.lower().lstrip('.') == 'drawio':\n                    _ = draw_io.DrawIOMetadataValidator(template_file)\n                else:\n                    logger.info(\n                        f'File: {self.rel_dir(template_file)} within the template directory was ignored'\n                        + ' as it is not markdown.'\n                    )\n            except Exception as ex:\n                raise TrestleError(\n                    f'Template file {self.rel_dir(template_file)} for task {self.task_name}'\n                    + f' failed to validate due to {ex}'\n                )\n        logger.info(f'TEMPLATES VALID: {self.task_name}.')\n        return CmdReturnCodes.SUCCESS.value\n\n    def _measure_template_folder(\n        self,\n        instance_dir: pathlib.Path,\n        validate_header: bool,\n        validate_only_header: bool,\n        governed_heading: str,\n        readme_validate: bool,\n        template_version: str,\n        ignore: str,\n        validate_by_type_field: bool,\n    ) -> bool:\n\"\"\"\n        Validate instances against templates.\n\n        Validation will succeed if:\n            1. All template files from the specified version are present in the task\n            2. All of the instances are valid\n        \"\"\"\n        all_versioned_templates: Dict[str, Any] = {}\n        instance_version = template_version\n        instance_file_names: List[pathlib.Path] = []\n        # Fetch all instances versions and build dictionary of required template files\n        for instance_file in instance_dir.iterdir():\n            if not file_utils.is_local_and_visible(instance_file):\n                continue\n            if not instance_file.is_file():\n                continue\n            if instance_file.name.lower() == 'readme.md' and not readme_validate:\n                continue\n            if ignore:\n                p = re.compile(ignore)\n                matched = p.match(instance_file.parts[-1])\n                if matched is not None:\n                    logger.info(f'Ignoring file {instance_file} from validation.')\n                    continue\n            instance_file_name = instance_file.relative_to(instance_dir)\n            instance_file_names.append(instance_file_name)\n            if instance_file.suffix == const.MARKDOWN_FILE_EXT:\n                md_api = MarkdownAPI()\n                versioned_template_dir = None\n                # checks on naming template name out of type header if needed\n                if validate_by_type_field:\n                    template_name = md_api.processor.fetch_value_from_header(\n                        instance_file, author_const.TEMPLATE_TYPE_HEADER\n                    )\n                    if template_name is None:\n                        logger.warning(\n                            f'INVALID: Instance file {instance_file_name} does not have'\n                            f' {author_const.TEMPLATE_TYPE_HEADER}'\n                            ' field in its header and can not be validated using optional parameter validate'\n                            ' template type field'\n                        )\n                        return False\n                    template_name = template_name + '.md'\n                else:\n                    template_name = instance_file_name\n                if template_version != '':\n                    template_file = self.template_dir / template_name\n                    versioned_template_dir = self.template_dir\n                else:\n                    instance_version = md_api.processor.fetch_value_from_header(\n                        instance_file, author_const.TEMPLATE_VERSION_HEADER\n                    )\n                    if instance_version is None:\n                        instance_version = '0.0.1'  # backward compatibility\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n                    template_file = versioned_template_dir / template_name\n\n                # Check if instance is in the available templates,\n                # additional files are allowed but should not be validated.\n                templates = self._get_templates(versioned_template_dir, readme_validate)\n                is_template_present = False\n                template_type_is_valid = False\n                for template in templates:\n                    # checks if valdation needs to check on x-trestle-template-type field on header\n                    if validate_by_type_field:\n                        instance_template_type = md_api.processor.fetch_value_from_header(\n                            instance_file, author_const.TEMPLATE_TYPE_HEADER\n                        )\n                        if template.stem == instance_template_type:\n                            is_template_present = True\n                            template_type_is_valid = True\n                            break\n                    # validation through template type field is not needed and performs validation\n                    # through file name flow as usual\n                    else:\n                        if template.name == str(instance_file_name):\n                            is_template_present = True\n                            break\n\n                if not is_template_present:\n                    logger.info(\n                        f'INFO: File{instance_file} will not be validated '\n                        f'as its name does not match any template file.'\n                    )\n                    continue\n\n                if instance_version not in all_versioned_templates.keys():\n                    all_versioned_templates[instance_version] = dict.fromkeys(\n                        [t.relative_to(versioned_template_dir) for t in templates], False\n                    )\n\n                if instance_file_name in all_versioned_templates[instance_version] or template_type_is_valid:\n                    # validate\n                    md_api.load_validator_with_template(\n                        template_file, validate_header, not validate_only_header, governed_heading\n                    )\n                    status = md_api.validate_instance(instance_file)\n                    if not status:\n                        logger.warning(\n                            f'INVALID: Markdown file {instance_file} failed validation against' + f' {template_file}'\n                        )\n                        return False\n                    else:\n                        logger.info(f'VALID: {instance_file}')\n                    # mark template as present\n                    if template_type_is_valid:\n                        template_file_name = [\n                            temp.relative_to(versioned_template_dir) for temp in templates if temp.name == template_name\n                        ]\n                        all_versioned_templates[instance_version][template_file_name[0]] = True\n                    else:\n                        all_versioned_templates[instance_version][instance_file_name] = True\n\n            elif instance_file.suffix == const.DRAWIO_FILE_EXT:\n                drawio = draw_io.DrawIO(instance_file)\n                metadata = drawio.get_metadata()[0]\n                versioned_template_dir = None\n                if template_version != '':\n                    template_file = self.template_dir / instance_file_name\n                    versioned_template_dir = self.template_dir\n                else:\n                    if author_const.TEMPLATE_VERSION_HEADER in metadata.keys():\n                        instance_version = metadata[author_const.TEMPLATE_VERSION_HEADER]\n                    else:\n                        instance_version = '0.0.1'  # backward compatibility\n\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n                    template_file = versioned_template_dir / instance_file_name\n\n                if instance_version not in all_versioned_templates.keys():\n                    templates = self._get_templates(versioned_template_dir, readme_validate)\n\n                    all_versioned_templates[instance_version] = dict.fromkeys(\n                        [t.relative_to(versioned_template_dir) for t in templates], False\n                    )\n\n                if instance_file_name in all_versioned_templates[instance_version]:\n                    # validate\n                    drawio_validator = draw_io.DrawIOMetadataValidator(template_file)\n                    status = drawio_validator.validate(instance_file)\n                    if not status:\n                        logger.warning(\n                            f'INVALID: Drawio file {instance_file} failed validation against' + f' {template_file}'\n                        )\n                        return False\n                    else:\n                        logger.info(f'VALID: {instance_file}')\n                    # mark template as present\n                    all_versioned_templates[instance_version][instance_file_name] = True\n\n            else:\n                logger.debug(f'Unsupported extension of the instance file: {instance_file}, will not be validated.')\n\n        # Check that all template files are present\n        for version in all_versioned_templates.keys():\n            for template in all_versioned_templates[version]:\n                if not all_versioned_templates[version][template]:\n                    logger.warning(\n                        f'Required template file {template} does not exist in measured instance' + f'{instance_dir}'\n                    )\n                    return False\n\n        return True\n\n    def _get_templates(self, versioned_template_dir: pathlib.Path, readme_validate: bool) -> List[pathlib.Path]:\n\"\"\"Get templates for the given version.\"\"\"\n        templates = list(\n            filter(\n                lambda p: file_utils.is_local_and_visible(p) and p.is_file()\n                and  # noqa: W504 - conflicting lint and formatting\n                (p.suffix == const.MARKDOWN_FILE_EXT or p.suffix == const.DRAWIO_FILE_EXT),\n                versioned_template_dir.iterdir()\n            )\n        )\n        if not readme_validate:\n            templates = list(filter(lambda p: p.name.lower() != 'readme.md', templates))\n\n        return templates\n\n    def create_sample(self) -> int:\n\"\"\"\n        Create a sample folder within the task and populate with template content.\n\n        Returns:\n            Unix return code for running sample as a command.\n        \"\"\"\n        ii = 0\n        while True:\n            sample_path = self.task_path / f'sample_folder_{ii}'\n            if sample_path.exists():\n                ii = ii + 1\n                continue\n            shutil.copytree(str(self.template_dir), str(sample_path))\n            return CmdReturnCodes.SUCCESS.value\n\n    def validate(\n        self,\n        validate_header: bool,\n        validate_only_header: bool,\n        governed_heading: str,\n        readme_validate: bool,\n        template_version: str,\n        ignore: str,\n        validate_by_type_field: bool,\n    ) -> int:\n\"\"\"Validate task.\"\"\"\n        if not self.task_path.is_dir():\n            raise TrestleError(f'Task directory {self.task_path} does not exist. Exiting validate.')\n\n        for task_instance in self.task_path.iterdir():\n            if task_instance.is_dir():\n                if file_utils.is_symlink(task_instance):\n                    continue\n                result = self._measure_template_folder(\n                    task_instance,\n                    validate_header,\n                    validate_only_header,\n                    governed_heading,\n                    readme_validate,\n                    template_version,\n                    ignore,\n                    validate_by_type_field\n                )\n                if not result:\n                    raise TrestleError(\n                        'Governed-folder validation failed for task'\n                        + f'{self.task_name} on directory {self.rel_dir(task_instance)}'\n                    )\n            else:\n                logger.info(\n                    f'Unexpected file {self.rel_dir(task_instance)} identified in {self.task_name}'\n                    + ' directory, ignoring.'\n                )\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.create_sample","title":"create_sample(self)","text":"

                                    Create a sample folder within the task and populate with template content.

                                    Returns:

                                    Type Description int

                                    Unix return code for running sample as a command.

                                    Source code in trestle/core/commands/author/folders.py
                                    def create_sample(self) -> int:\n\"\"\"\n    Create a sample folder within the task and populate with template content.\n\n    Returns:\n        Unix return code for running sample as a command.\n    \"\"\"\n    ii = 0\n    while True:\n        sample_path = self.task_path / f'sample_folder_{ii}'\n        if sample_path.exists():\n            ii = ii + 1\n            continue\n        shutil.copytree(str(self.template_dir), str(sample_path))\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.setup_template","title":"setup_template(self, template_version)","text":"

                                    Create structure to allow markdown template enforcement.

                                    Source code in trestle/core/commands/author/folders.py
                                    def setup_template(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\"\"\"\n    if not self.task_path.exists():\n        self.task_path.mkdir(exist_ok=True, parents=True)\n    elif self.task_path.is_file():\n        raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n    if not self.template_dir.exists():\n        self.template_dir.mkdir(exist_ok=True, parents=True)\n    elif self.template_dir.is_file():\n        raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n\n    template_file_a_md = self.template_dir / 'a_template.md'\n    template_file_another_md = self.template_dir / 'another_template.md'\n    template_file_drawio = self.template_dir / 'architecture.drawio'\n    TemplateVersioning.write_versioned_template(\n        'template.md', self.template_dir, template_file_a_md, template_version\n    )\n    TemplateVersioning.write_versioned_template(\n        'template.md', self.template_dir, template_file_another_md, template_version\n    )\n    TemplateVersioning.write_versioned_template(\n        'template.drawio', self.template_dir, template_file_drawio, template_version\n    )\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.template_validate","title":"template_validate(self, validate_header, validate_only_header, heading, readme_validate)","text":"

                                    Validate that the template is acceptable markdown.

                                    Source code in trestle/core/commands/author/folders.py
                                    def template_validate(\n    self, validate_header: bool, validate_only_header: bool, heading: str, readme_validate: bool\n) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n    if not self.template_dir.is_dir():\n        raise TrestleError(\n            f'Template directory {self.rel_dir(self.template_dir)} for task {self.task_name} does not exist.'\n        )\n    # get list of files:\n    template_files = self.template_dir.rglob('*')\n\n    for template_file in template_files:\n        try:\n            if not file_utils.is_local_and_visible(template_file):\n                continue\n            elif template_file.is_dir():\n                continue\n            elif template_file.suffix.lower() == const.MARKDOWN_FILE_EXT:\n                if not readme_validate and template_file.name == 'readme.md':\n                    raise TrestleError('Template directory contains a readme.md file and readme validation is off.')\n\n                md_api = MarkdownAPI()\n                md_api.load_validator_with_template(\n                    template_file, validate_header, not validate_only_header, heading\n                )\n            elif template_file.suffix.lower().lstrip('.') == 'drawio':\n                _ = draw_io.DrawIOMetadataValidator(template_file)\n            else:\n                logger.info(\n                    f'File: {self.rel_dir(template_file)} within the template directory was ignored'\n                    + ' as it is not markdown.'\n                )\n        except Exception as ex:\n            raise TrestleError(\n                f'Template file {self.rel_dir(template_file)} for task {self.task_name}'\n                + f' failed to validate due to {ex}'\n            )\n    logger.info(f'TEMPLATES VALID: {self.task_name}.')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.validate","title":"validate(self, validate_header, validate_only_header, governed_heading, readme_validate, template_version, ignore, validate_by_type_field)","text":"

                                    Validate task.

                                    Source code in trestle/core/commands/author/folders.py
                                    def validate(\n    self,\n    validate_header: bool,\n    validate_only_header: bool,\n    governed_heading: str,\n    readme_validate: bool,\n    template_version: str,\n    ignore: str,\n    validate_by_type_field: bool,\n) -> int:\n\"\"\"Validate task.\"\"\"\n    if not self.task_path.is_dir():\n        raise TrestleError(f'Task directory {self.task_path} does not exist. Exiting validate.')\n\n    for task_instance in self.task_path.iterdir():\n        if task_instance.is_dir():\n            if file_utils.is_symlink(task_instance):\n                continue\n            result = self._measure_template_folder(\n                task_instance,\n                validate_header,\n                validate_only_header,\n                governed_heading,\n                readme_validate,\n                template_version,\n                ignore,\n                validate_by_type_field\n            )\n            if not result:\n                raise TrestleError(\n                    'Governed-folder validation failed for task'\n                    + f'{self.task_name} on directory {self.rel_dir(task_instance)}'\n                )\n        else:\n            logger.info(\n                f'Unexpected file {self.rel_dir(task_instance)} identified in {self.task_name}'\n                + ' directory, ignoring.'\n            )\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.headers/","title":"headers","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers","title":"trestle.core.commands.author.headers","text":"

                                    Trestle author headers command.

                                    "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers","title":" Headers (AuthorCommonCommand) ","text":"

                                    Enforce header / metadata across file types supported by author (markdown and drawio).

                                    Source code in trestle/core/commands/author/headers.py
                                    class Headers(AuthorCommonCommand):\n\"\"\"Enforce header / metadata across file types supported by author (markdown and drawio).\"\"\"\n\n    name = 'headers'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            author_const.RECURSE_SHORT, author_const.RECURSE_LONG, help=author_const.RECURSE_HELP, action='store_true'\n        )\n        self.add_argument(author_const.MODE_ARG_NAME, choices=author_const.MODE_CHOICES)\n        tn_help_str = '\\n'.join(\n            [\n                'The name of the the task to be governed.',\n                '',\n                'The template files for header metadata governance are located at .trestle/author/[task name]',\n                'Currently supported types are:',\n                'Markdown: .trestle/author/[task name]/template.md',\n                'Drawio: .trestle/author/[task name]/template.drawio',\n                '',\n                'Note that by default this will automatically enforce the task.'\n            ]\n        )\n        self.add_argument(\n            author_const.TASK_NAME_SHORT, author_const.TASK_NAME_LONG, help=tn_help_str, type=str, default=None\n        )\n        self.add_argument(\n            author_const.SHORT_README_VALIDATE,\n            author_const.LONG_README_VALIDATE,\n            help=author_const.README_VALIDATE_HELP,\n            action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_TEMPLATE_VERSION,\n            author_const.LONG_TEMPLATE_VERSION,\n            help=author_const.TEMPLATE_VERSION_HELP,\n            action='store'\n        )\n        self.add_argument(\n            author_const.SHORT_IGNORE, author_const.LONG_IGNORE, help=author_const.IGNORE_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.GLOBAL_SHORT, author_const.GLOBAL_LONG, help=author_const.GLOBAL_HELP, action='store_true'\n        )\n        self.add_argument(\n            author_const.EXCLUDE_SHORT,\n            author_const.EXCLUDE_LONG,\n            help=author_const.EXCLUDE_HELP,\n            type=pathlib.Path,\n            nargs='*',\n            default=None\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            status = 1\n            if self._initialize(args):\n                return status\n            # Handle conditional requirement of args.task_name\n            # global is special so we need to use get attribute.\n            if not self.global_ and not self.task_name:\n                logger.warning('Task name (-tn) argument is required when global is not specified')\n                return status\n\n            if args.exclude:\n                logger.warning('--exclude or -e is deprecated, use --ignore instead.')\n\n            if args.mode == 'create-sample':\n                status = self.create_sample()\n\n            elif args.mode == 'template-validate':\n                status = self.template_validate()\n            elif args.mode == 'setup':\n                status = self.setup(args.template_version)\n            elif args.mode == 'validate':\n                exclusions = []\n                if args.exclude:\n                    exclusions = args.exclude\n                # mode is validate\n                status = self.validate(\n                    args.recurse, args.readme_validate, exclusions, args.template_version, args.ignore\n                )\n            return status\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle author headers')\n\n    def create_sample(self) -> int:\n\"\"\"Create sample object, this always defaults to markdown.\"\"\"\n        logger.info('Header only validation does not support sample creation.')\n        logger.info('Exiting')\n        return CmdReturnCodes.SUCCESS.value\n\n    def setup(self, template_version: str) -> int:\n\"\"\"Create template directory and templates.\"\"\"\n        # Step 1 - validation\n\n        if self.task_name and not self.task_path.exists():\n            self.task_path.mkdir(exist_ok=True, parents=True)\n        elif self.task_name and self.task_path.is_file():\n            raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n\n        if not self.template_dir.exists():\n            self.template_dir.mkdir(exist_ok=True, parents=True)\n        logger.info(f'Populating template files to {self.rel_dir(self.template_dir)}')\n        for template in author_const.REFERENCE_TEMPLATES.values():\n            destination_path = self.template_dir / template\n            TemplateVersioning.write_versioned_template(template, self.template_dir, destination_path, template_version)\n\n            logger.info(f'Template directory populated {self.rel_dir(destination_path)}')\n        return CmdReturnCodes.SUCCESS.value\n\n    def template_validate(self) -> int:\n\"\"\"Validate the integrity of the template files.\"\"\"\n        logger.info('Checking template file integrity')\n        for template_file in self.template_dir.iterdir():\n            if (template_file.name not in author_const.REFERENCE_TEMPLATES.values()\n                    and template_file.name.lower() != 'readme.md'):\n                raise TrestleError(f'Unexpected template file {self.rel_dir(template_file)}')\n\n            if template_file.suffix == const.MARKDOWN_FILE_EXT:\n                try:\n                    md_api = MarkdownAPI()\n                    md_api.load_validator_with_template(template_file, True, False)\n                except Exception as ex:\n                    raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n            elif template_file.suffix == const.DRAWIO_FILE_EXT:\n                try:\n                    _ = DrawIOMetadataValidator(template_file)\n                except Exception as ex:\n                    raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n        logger.info('Templates validated')\n        return CmdReturnCodes.SUCCESS.value\n\n    def _validate_dir(\n        self,\n        candidate_dir: pathlib.Path,\n        recurse: bool,\n        readme_validate: bool,\n        relative_exclusions: List[pathlib.Path],\n        template_version: str,\n        ignore: str\n    ) -> bool:\n\"\"\"Validate a directory within the trestle workspace.\"\"\"\n        all_versioned_templates: Dict[str, Any] = {}\n        instance_version = template_version\n        instance_file_names: List[pathlib.Path] = []\n        # Fetch all instances versions and build dictionary of required template files\n        instances = list(candidate_dir.iterdir())\n        if recurse:\n            instances = candidate_dir.rglob('*')\n            if ignore:\n                p = re.compile(ignore)\n                instances = list(\n                    filter(\n                        lambda f: len(list(filter(p.match, str(f.relative_to(candidate_dir)).split('/')))) == 0,\n                        instances\n                    )\n                )\n        for instance_file in instances:\n            if not file_utils.is_local_and_visible(instance_file):\n                continue\n            if instance_file.name.lower() == 'readme.md' and not readme_validate:\n                continue\n            if instance_file.is_dir() and not recurse:\n                continue\n            if any(str(ex) in str(instance_file) for ex in relative_exclusions):\n                continue\n            if ignore:\n                p = re.compile(ignore)\n                matched = p.match(instance_file.parts[-1])\n                if matched is not None:\n                    logger.info(f'Ignoring file {instance_file} from validation.')\n                    continue\n            instance_file_name = instance_file.relative_to(candidate_dir)\n            instance_file_names.append(instance_file_name)\n            if instance_file.suffix == const.MARKDOWN_FILE_EXT:\n                md_api = MarkdownAPI()\n                versioned_template_dir = None\n                if template_version != '':\n                    versioned_template_dir = self.template_dir\n                else:\n                    instance_version = md_api.processor.fetch_value_from_header(\n                        instance_file, author_const.TEMPLATE_VERSION_HEADER\n                    )\n                    if instance_version is None:\n                        instance_version = '0.0.1'  # backward compatibility\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n\n                if instance_version not in all_versioned_templates.keys():\n                    templates = list(\n                        filter(lambda p: file_utils.is_local_and_visible(p), versioned_template_dir.iterdir())\n                    )\n                    if not readme_validate:\n                        templates = list(filter(lambda p: p.name.lower() != 'readme.md', templates))\n                    self._update_templates(all_versioned_templates, templates, instance_version)\n\n                # validate\n                md_api.load_validator_with_template(all_versioned_templates[instance_version]['md'], True, False)\n                status = md_api.validate_instance(instance_file)\n                if not status:\n                    logger.info(f'INVALID: {self.rel_dir(instance_file)}')\n                    return False\n                else:\n                    logger.info(f'VALID: {self.rel_dir(instance_file)}')\n\n            elif instance_file.suffix == const.DRAWIO_FILE_EXT:\n                drawio = DrawIO(instance_file)\n                metadata = drawio.get_metadata()[0]\n\n                versioned_template_dir = None\n                if template_version != '':\n                    versioned_template_dir = self.template_dir\n                else:\n                    if author_const.TEMPLATE_VERSION_HEADER in metadata.keys():\n                        instance_version = metadata[author_const.TEMPLATE_VERSION_HEADER]\n                    else:\n                        instance_version = '0.0.1'  # backward compatibility\n\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n\n                if instance_version not in all_versioned_templates.keys():\n                    templates = list(\n                        filter(lambda p: file_utils.is_local_and_visible(p), versioned_template_dir.iterdir())\n                    )\n                    if not readme_validate:\n                        templates = list(filter(lambda p: p.name.lower() != 'readme.md', templates))\n                    self._update_templates(all_versioned_templates, templates, instance_version)\n\n                # validate\n                drawio_validator = DrawIOMetadataValidator(all_versioned_templates[instance_version]['drawio'])\n                status = drawio_validator.validate(instance_file)\n                if not status:\n                    logger.info(f'INVALID: {self.rel_dir(instance_file)}')\n                    return False\n                else:\n                    logger.info(f'VALID: {self.rel_dir(instance_file)}')\n\n            else:\n                logger.debug(f'Unsupported extension of the instance file: {instance_file}, will not be validated.')\n\n        return True\n\n    def _update_templates(\n        self, all_versioned_templates: Dict[str, Dict[str, str]], templates: List[str], instance_version: str\n    ) -> None:\n        all_versioned_templates[instance_version] = {}\n        all_drawio_templates = list(filter(lambda p: p.suffix == const.DRAWIO_FILE_EXT, templates))\n        all_md_templates = list(filter(lambda p: p.suffix == const.MARKDOWN_FILE_EXT, templates))\n        if all_drawio_templates:\n            all_versioned_templates[instance_version]['drawio'] = all_drawio_templates[0]\n        if all_md_templates:\n            all_versioned_templates[instance_version]['md'] = all_md_templates[0]\n\n    def validate(\n        self,\n        recurse: bool,\n        readme_validate: bool,\n        relative_excludes: List[pathlib.Path],\n        template_version: str,\n        ignore: str\n    ) -> int:\n\"\"\"Run validation based on available templates.\"\"\"\n        paths = []\n        if self.task_name:\n            if not self.task_path.is_dir():\n                raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n            paths = [self.task_path]\n        else:\n            for path in self.trestle_root.iterdir():\n                relative_path = path.relative_to(self.trestle_root)\n                # Files in the root directory must be exclused\n                if path.is_file():\n                    continue\n                if not file_utils.is_directory_name_allowed(path):\n                    continue\n                if str(relative_path).rstrip('/') in const.MODEL_DIR_LIST:\n                    continue\n                if (relative_path in relative_excludes):\n                    continue\n                if not file_utils.is_hidden(path):\n                    paths.append(path)\n\n        for path in paths:\n            try:\n                valid = self._validate_dir(path, recurse, readme_validate, relative_excludes, template_version, ignore)\n                if not valid:\n                    logger.info(f'validation failed on {path}')\n                    return CmdReturnCodes.DOCUMENTS_VALIDATION_ERROR.value\n            except Exception as e:\n                raise TrestleError(f'Error during header validation on {path} {e}')\n\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.create_sample","title":"create_sample(self)","text":"

                                    Create sample object, this always defaults to markdown.

                                    Source code in trestle/core/commands/author/headers.py
                                    def create_sample(self) -> int:\n\"\"\"Create sample object, this always defaults to markdown.\"\"\"\n    logger.info('Header only validation does not support sample creation.')\n    logger.info('Exiting')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.setup","title":"setup(self, template_version)","text":"

                                    Create template directory and templates.

                                    Source code in trestle/core/commands/author/headers.py
                                    def setup(self, template_version: str) -> int:\n\"\"\"Create template directory and templates.\"\"\"\n    # Step 1 - validation\n\n    if self.task_name and not self.task_path.exists():\n        self.task_path.mkdir(exist_ok=True, parents=True)\n    elif self.task_name and self.task_path.is_file():\n        raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n\n    if not self.template_dir.exists():\n        self.template_dir.mkdir(exist_ok=True, parents=True)\n    logger.info(f'Populating template files to {self.rel_dir(self.template_dir)}')\n    for template in author_const.REFERENCE_TEMPLATES.values():\n        destination_path = self.template_dir / template\n        TemplateVersioning.write_versioned_template(template, self.template_dir, destination_path, template_version)\n\n        logger.info(f'Template directory populated {self.rel_dir(destination_path)}')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.template_validate","title":"template_validate(self)","text":"

                                    Validate the integrity of the template files.

                                    Source code in trestle/core/commands/author/headers.py
                                    def template_validate(self) -> int:\n\"\"\"Validate the integrity of the template files.\"\"\"\n    logger.info('Checking template file integrity')\n    for template_file in self.template_dir.iterdir():\n        if (template_file.name not in author_const.REFERENCE_TEMPLATES.values()\n                and template_file.name.lower() != 'readme.md'):\n            raise TrestleError(f'Unexpected template file {self.rel_dir(template_file)}')\n\n        if template_file.suffix == const.MARKDOWN_FILE_EXT:\n            try:\n                md_api = MarkdownAPI()\n                md_api.load_validator_with_template(template_file, True, False)\n            except Exception as ex:\n                raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n        elif template_file.suffix == const.DRAWIO_FILE_EXT:\n            try:\n                _ = DrawIOMetadataValidator(template_file)\n            except Exception as ex:\n                raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n    logger.info('Templates validated')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.validate","title":"validate(self, recurse, readme_validate, relative_excludes, template_version, ignore)","text":"

                                    Run validation based on available templates.

                                    Source code in trestle/core/commands/author/headers.py
                                    def validate(\n    self,\n    recurse: bool,\n    readme_validate: bool,\n    relative_excludes: List[pathlib.Path],\n    template_version: str,\n    ignore: str\n) -> int:\n\"\"\"Run validation based on available templates.\"\"\"\n    paths = []\n    if self.task_name:\n        if not self.task_path.is_dir():\n            raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n        paths = [self.task_path]\n    else:\n        for path in self.trestle_root.iterdir():\n            relative_path = path.relative_to(self.trestle_root)\n            # Files in the root directory must be exclused\n            if path.is_file():\n                continue\n            if not file_utils.is_directory_name_allowed(path):\n                continue\n            if str(relative_path).rstrip('/') in const.MODEL_DIR_LIST:\n                continue\n            if (relative_path in relative_excludes):\n                continue\n            if not file_utils.is_hidden(path):\n                paths.append(path)\n\n    for path in paths:\n        try:\n            valid = self._validate_dir(path, recurse, readme_validate, relative_excludes, template_version, ignore)\n            if not valid:\n                logger.info(f'validation failed on {path}')\n                return CmdReturnCodes.DOCUMENTS_VALIDATION_ERROR.value\n        except Exception as e:\n            raise TrestleError(f'Error during header validation on {path} {e}')\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.jinja/","title":"jinja","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja","title":"trestle.core.commands.author.jinja","text":"

                                    Trestle Commands.

                                    "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd","title":" JinjaCmd (CommandPlusDocs) ","text":"

                                    Transform an input template to an output document using jinja templating.

                                    Source code in trestle/core/commands/author/jinja.py
                                    class JinjaCmd(CommandPlusDocs):\n\"\"\"Transform an input template to an output document using jinja templating.\"\"\"\n\n    max_recursion_depth = 2\n\n    name = 'jinja'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-i', '--input', help='Input jinja template, relative to trestle root', required=True)\n        self.add_argument('-o', '--output', help='Output template, relative to trestle root.', required=True)\n        self.add_argument(\n            '-lut',\n            '--look-up-table',\n            help='Key-value pair table, stored as yaml, to be passed to jinja as variables',\n            required=False\n        )\n        self.add_argument(\n            '-elp',\n            '--external-lut-prefix',\n            help='Prefix paths for LUT, to maintain compatibility with other templating systems',\n            required=False\n        )\n        self.add_argument(\n            '-nc',\n            '--number-captions',\n            help='Add incremental numbering to table and image captions, in the form Table n - ... and Figure n - ...',\n            action='store_true'\n        )\n        self.add_argument(\n            '-bf',\n            '--bracket-format',\n            help='With -sv, allows brackets around value, e.g. [.] or ((.)), with the dot representing the value.',\n            required=False\n        )\n        self.add_argument(\n            '-vap',\n            '--value-assigned-prefix',\n            help='Places a prefix in front of the parameter string if a value has been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-vnap',\n            '--value-not-assigned-prefix',\n            help='Places a prefix in front of the parameter string if a value has *not* been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-ssp', '--system-security-plan', help='An optional SSP to be passed', default=None, required=False\n        )\n        self.add_argument('-p', '--profile', help='An optional profile to be passed', default=None, required=False)\n        self.add_argument(\n            '-dp',\n            '--docs-profile',\n            help='Output profile controls to separate markdown files',\n            action='store_true',\n            required=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> None:\n        try:\n            log.set_log_level_from_args(args)\n            logger.debug(f'Starting {self.name} command')\n            input_path = pathlib.Path(args.input)\n            output_path = pathlib.Path(args.output)\n\n            logger.debug(f'input_path: {input_path}')\n            logger.debug(f'output_path: {output_path}')\n            logger.debug(f'system_security_plan path: {args.system_security_plan}')\n            logger.debug(f'profile: {args.profile}')\n            logger.debug(f'docs_profile: {args.docs_profile}')\n            logger.debug(f'lookup_table: {args.look_up_table}')\n\n            if args.system_security_plan and args.docs_profile:\n                raise TrestleIncorrectArgsError('Output to multiple files is possible with profile only.')\n\n            if args.docs_profile and not args.profile:\n                raise TrestleIncorrectArgsError('Profile must be provided to output to multiple files.')\n\n            lut = {}\n            if args.look_up_table:\n                lut_table = pathlib.Path(args.look_up_table)\n                lookup_table_path = pathlib.Path.cwd() / lut_table\n                lut = JinjaCmd.load_LUT(lookup_table_path, args.external_lut_prefix)\n\n            if args.profile and args.docs_profile:\n                return JinjaCmd.jinja_multiple_md(\n                    pathlib.Path(args.trestle_root),\n                    input_path,\n                    output_path,\n                    args.profile,\n                    lut,\n                    parameters_formatting=args.bracket_format,\n                    value_assigned_prefix=args.value_assigned_prefix,\n                    value_not_assigned_prefix=args.value_not_assigned_prefix\n                )\n\n            return JinjaCmd.jinja_ify(\n                pathlib.Path(args.trestle_root),\n                input_path,\n                output_path,\n                args.system_security_plan,\n                args.profile,\n                lut,\n                number_captions=args.number_captions,\n                parameters_formatting=args.bracket_format,\n                value_assigned_prefix=args.value_assigned_prefix,\n                value_not_assigned_prefix=args.value_not_assigned_prefix\n            )\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(  # type: ignore\n                e, logger, 'Error while generating markdown via Jinja template'\n            )\n\n    @staticmethod\n    def load_LUT(path: pathlib.Path, prefix: Optional[str]) -> Dict[str, Any]:  # noqa: N802\n\"\"\"Load a Yaml lookup table from file.\"\"\"\n        yaml = YAML()\n        lut = yaml.load(path.open('r', encoding=const.FILE_ENCODING))\n        if prefix:\n            prefixes = prefix.split('.')\n            while prefixes:\n                old_lut = lut\n                lut[prefixes.pop(-1)] = old_lut\n\n        return lut\n\n    @staticmethod\n    def jinja_ify(\n        trestle_root: pathlib.Path,\n        r_input_file: pathlib.Path,\n        r_output_file: pathlib.Path,\n        ssp: Optional[str],\n        profile: Optional[str],\n        lut: Dict[str, Any],\n        number_captions: Optional[bool] = False,\n        parameters_formatting: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> int:\n\"\"\"Run jinja over an input file with additional booleans.\"\"\"\n        template_folder = pathlib.Path.cwd()\n        jinja_env = Environment(\n            loader=FileSystemLoader(template_folder),\n            extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n            trim_blocks=True,\n            autoescape=True\n        )\n        template = jinja_env.get_template(str(r_input_file))\n        # create boolean dict\n        if operator.xor(bool(ssp), bool(profile)):\n            raise TrestleIncorrectArgsError('Both SSP and profile should be provided or not at all')\n\n        if ssp:\n            # name lookup\n            ssp_data, _ = load_validate_model_name(trestle_root, ssp, SystemSecurityPlan)\n            lut['ssp'] = ssp_data\n            profile_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, profile, Profile)\n            profile_resolver = ProfileResolver()\n            resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n                trestle_root,\n                profile_path,\n                False,\n                False,\n                parameters_formatting,\n                ParameterRep.ASSIGNMENT_FORM,\n                False,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n\n            ssp_writer = SSPMarkdownWriter(trestle_root)\n            ssp_writer.set_ssp(ssp_data)\n            ssp_writer.set_catalog(resolved_catalog)\n            lut['catalog'] = resolved_catalog\n            lut['catalog_interface'] = CatalogInterface(resolved_catalog)\n            lut['control_interface'] = ControlInterface()\n            lut['control_writer'] = DocsControlWriter()\n            lut['ssp_md_writer'] = ssp_writer\n\n        output = JinjaCmd.render_template(template, lut, template_folder)\n\n        output_file = trestle_root / r_output_file\n        if number_captions:\n            output_file.open('w', encoding=const.FILE_ENCODING).write(_number_captions(output))\n        else:\n            output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def jinja_multiple_md(\n        trestle_root: pathlib.Path,\n        r_input_file: pathlib.Path,\n        r_output_file: pathlib.Path,\n        profile_name: Optional[str],\n        lut: Dict[str, Any],\n        parameters_formatting: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> int:\n\"\"\"Output profile as multiple markdown files using Jinja.\"\"\"\n        template_folder = pathlib.Path.cwd()\n\n        # Output to multiple markdown files\n        profile, profile_path = ModelUtils.load_model_for_class(trestle_root, profile_name, Profile)\n        profile_resolver = ProfileResolver()\n        resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            False,\n            False,\n            parameters_formatting,\n            ParameterRep.ASSIGNMENT_FORM,\n            False,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        catalog_interface = CatalogInterface(resolved_catalog)\n\n        # Generate a single markdown page for each control per each group\n        for group in catalog_interface.get_all_groups_from_catalog():\n            for control in catalog_interface.get_sorted_controls_in_group(group.id):\n                _, group_title, _ = catalog_interface.get_group_info_by_control(control.id)\n                group_dir = r_output_file\n                control_path = catalog_interface.get_control_path(control.id)\n                for sub_dir in control_path:\n                    group_dir = group_dir / sub_dir\n                    if not group_dir.exists():\n                        group_dir.mkdir(parents=True, exist_ok=True)\n\n                control_writer = DocsControlWriter()\n\n                jinja_env = Environment(\n                    loader=FileSystemLoader(template_folder),\n                    extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n                    trim_blocks=True,\n                    autoescape=True\n                )\n                template = jinja_env.get_template(str(r_input_file))\n                lut['catalog_interface'] = catalog_interface\n                lut['control_interface'] = ControlInterface()\n                lut['control_writer'] = control_writer\n                lut['control'] = control\n                lut['profile'] = profile\n                lut['group_title'] = group_title\n                output = JinjaCmd.render_template(template, lut, template_folder)\n\n                output_file = trestle_root / group_dir / pathlib.Path(control.id + const.MARKDOWN_FILE_EXT)\n                output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def render_template(template: Template, lut: Dict[str, Any], template_folder: pathlib.Path) -> str:\n\"\"\"Render template.\"\"\"\n        new_output = template.render(**lut)\n        output = ''\n        # This recursion allows nesting within expressions (e.g. an expression can contain jinja templates).\n        error_countdown = JinjaCmd.max_recursion_depth\n        while new_output != output and error_countdown > 0:\n            error_countdown = error_countdown - 1\n            output = new_output\n            random_name = uuid.uuid4()  # Should be random and not used.\n            dict_loader = DictLoader({str(random_name): new_output})\n            jinja_env = Environment(\n                loader=ChoiceLoader([dict_loader, FileSystemLoader(template_folder)]),\n                extensions=[MDCleanInclude, MDSectionInclude, MDDatestamp],\n                autoescape=True,\n                trim_blocks=True\n            )\n            template = jinja_env.get_template(str(random_name))\n            new_output = template.render(**lut)\n\n        return output\n
                                    "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.max_recursion_depth","title":"max_recursion_depth","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.jinja_ify","title":"jinja_ify(trestle_root, r_input_file, r_output_file, ssp, profile, lut, number_captions=False, parameters_formatting=None, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                    Run jinja over an input file with additional booleans.

                                    Source code in trestle/core/commands/author/jinja.py
                                    @staticmethod\ndef jinja_ify(\n    trestle_root: pathlib.Path,\n    r_input_file: pathlib.Path,\n    r_output_file: pathlib.Path,\n    ssp: Optional[str],\n    profile: Optional[str],\n    lut: Dict[str, Any],\n    number_captions: Optional[bool] = False,\n    parameters_formatting: Optional[str] = None,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> int:\n\"\"\"Run jinja over an input file with additional booleans.\"\"\"\n    template_folder = pathlib.Path.cwd()\n    jinja_env = Environment(\n        loader=FileSystemLoader(template_folder),\n        extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n        trim_blocks=True,\n        autoescape=True\n    )\n    template = jinja_env.get_template(str(r_input_file))\n    # create boolean dict\n    if operator.xor(bool(ssp), bool(profile)):\n        raise TrestleIncorrectArgsError('Both SSP and profile should be provided or not at all')\n\n    if ssp:\n        # name lookup\n        ssp_data, _ = load_validate_model_name(trestle_root, ssp, SystemSecurityPlan)\n        lut['ssp'] = ssp_data\n        profile_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, profile, Profile)\n        profile_resolver = ProfileResolver()\n        resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            False,\n            False,\n            parameters_formatting,\n            ParameterRep.ASSIGNMENT_FORM,\n            False,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n\n        ssp_writer = SSPMarkdownWriter(trestle_root)\n        ssp_writer.set_ssp(ssp_data)\n        ssp_writer.set_catalog(resolved_catalog)\n        lut['catalog'] = resolved_catalog\n        lut['catalog_interface'] = CatalogInterface(resolved_catalog)\n        lut['control_interface'] = ControlInterface()\n        lut['control_writer'] = DocsControlWriter()\n        lut['ssp_md_writer'] = ssp_writer\n\n    output = JinjaCmd.render_template(template, lut, template_folder)\n\n    output_file = trestle_root / r_output_file\n    if number_captions:\n        output_file.open('w', encoding=const.FILE_ENCODING).write(_number_captions(output))\n    else:\n        output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.jinja_multiple_md","title":"jinja_multiple_md(trestle_root, r_input_file, r_output_file, profile_name, lut, parameters_formatting=None, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                    Output profile as multiple markdown files using Jinja.

                                    Source code in trestle/core/commands/author/jinja.py
                                    @staticmethod\ndef jinja_multiple_md(\n    trestle_root: pathlib.Path,\n    r_input_file: pathlib.Path,\n    r_output_file: pathlib.Path,\n    profile_name: Optional[str],\n    lut: Dict[str, Any],\n    parameters_formatting: Optional[str] = None,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> int:\n\"\"\"Output profile as multiple markdown files using Jinja.\"\"\"\n    template_folder = pathlib.Path.cwd()\n\n    # Output to multiple markdown files\n    profile, profile_path = ModelUtils.load_model_for_class(trestle_root, profile_name, Profile)\n    profile_resolver = ProfileResolver()\n    resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n        trestle_root,\n        profile_path,\n        False,\n        False,\n        parameters_formatting,\n        ParameterRep.ASSIGNMENT_FORM,\n        False,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    catalog_interface = CatalogInterface(resolved_catalog)\n\n    # Generate a single markdown page for each control per each group\n    for group in catalog_interface.get_all_groups_from_catalog():\n        for control in catalog_interface.get_sorted_controls_in_group(group.id):\n            _, group_title, _ = catalog_interface.get_group_info_by_control(control.id)\n            group_dir = r_output_file\n            control_path = catalog_interface.get_control_path(control.id)\n            for sub_dir in control_path:\n                group_dir = group_dir / sub_dir\n                if not group_dir.exists():\n                    group_dir.mkdir(parents=True, exist_ok=True)\n\n            control_writer = DocsControlWriter()\n\n            jinja_env = Environment(\n                loader=FileSystemLoader(template_folder),\n                extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n                trim_blocks=True,\n                autoescape=True\n            )\n            template = jinja_env.get_template(str(r_input_file))\n            lut['catalog_interface'] = catalog_interface\n            lut['control_interface'] = ControlInterface()\n            lut['control_writer'] = control_writer\n            lut['control'] = control\n            lut['profile'] = profile\n            lut['group_title'] = group_title\n            output = JinjaCmd.render_template(template, lut, template_folder)\n\n            output_file = trestle_root / group_dir / pathlib.Path(control.id + const.MARKDOWN_FILE_EXT)\n            output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.load_LUT","title":"load_LUT(path, prefix) staticmethod","text":"

                                    Load a Yaml lookup table from file.

                                    Source code in trestle/core/commands/author/jinja.py
                                    @staticmethod\ndef load_LUT(path: pathlib.Path, prefix: Optional[str]) -> Dict[str, Any]:  # noqa: N802\n\"\"\"Load a Yaml lookup table from file.\"\"\"\n    yaml = YAML()\n    lut = yaml.load(path.open('r', encoding=const.FILE_ENCODING))\n    if prefix:\n        prefixes = prefix.split('.')\n        while prefixes:\n            old_lut = lut\n            lut[prefixes.pop(-1)] = old_lut\n\n    return lut\n
                                    "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.render_template","title":"render_template(template, lut, template_folder) staticmethod","text":"

                                    Render template.

                                    Source code in trestle/core/commands/author/jinja.py
                                    @staticmethod\ndef render_template(template: Template, lut: Dict[str, Any], template_folder: pathlib.Path) -> str:\n\"\"\"Render template.\"\"\"\n    new_output = template.render(**lut)\n    output = ''\n    # This recursion allows nesting within expressions (e.g. an expression can contain jinja templates).\n    error_countdown = JinjaCmd.max_recursion_depth\n    while new_output != output and error_countdown > 0:\n        error_countdown = error_countdown - 1\n        output = new_output\n        random_name = uuid.uuid4()  # Should be random and not used.\n        dict_loader = DictLoader({str(random_name): new_output})\n        jinja_env = Environment(\n            loader=ChoiceLoader([dict_loader, FileSystemLoader(template_folder)]),\n            extensions=[MDCleanInclude, MDSectionInclude, MDDatestamp],\n            autoescape=True,\n            trim_blocks=True\n        )\n        template = jinja_env.get_template(str(random_name))\n        new_output = template.render(**lut)\n\n    return output\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/","title":"prof","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof","title":"trestle.core.commands.author.prof","text":"

                                    Author commands to generate profile as markdown and assemble to json after edit.

                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble","title":" ProfileAssemble (AuthorCommonCommand) ","text":"

                                    Assemble markdown files of controls into a Profile json file.

                                    Source code in trestle/core/commands/author/prof.py
                                    class ProfileAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into a Profile json file.\"\"\"\n\n    name = 'profile-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the profile model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the source markdown file directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json Profile (ok to overwrite original)'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-sp', '--set-parameters', action='store_true', help=const.HELP_SET_PARAMS, required=False)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n        self.add_argument('-s', '--sections', help=const.HELP_SECTIONS, required=False, type=str)\n        self.add_argument('-rs', '--required-sections', help=const.HELP_REQUIRED_SECTIONS, required=False, type=str)\n        self.add_argument('-as', '--allowed-sections', help=const.HELP_ALLOWED_SECTIONS, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n            return self.assemble_profile(\n                trestle_root=trestle_root,\n                parent_prof_name=args.name,\n                md_name=args.markdown,\n                assem_prof_name=args.output,\n                set_parameters_flag=args.set_parameters,\n                regenerate=args.regenerate,\n                version=args.version,\n                sections_dict=comma_colon_sep_to_dict(args.sections),\n                required_sections=comma_sep_to_list(args.required_sections),\n                allowed_sections=args.allowed_sections\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Assembly of markdown to profile failed')\n\n    @staticmethod\n    def _update_alter_adds(profile: prof.Profile, alters: List[prof.Alter], alter_dict: Dict) -> None:\n        for new_alter in alters:\n            alter = alter_dict.get(new_alter.control_id, None)\n            if not alter:\n                # the control did not have alters, so add\n                alter = prof.Alter(control_id=new_alter.control_id)\n            # even though we removed adds at start, we may have added one already\n            if alter.adds:\n                alter.adds.extend(new_alter.adds)\n            else:\n                alter.adds = new_alter.adds\n            # update the dict with the new alter with its added adds\n            alter_dict[new_alter.control_id] = alter\n\n    @staticmethod\n    def _replace_alter_adds(profile: prof.Profile, alters: List[prof.Alter]) -> bool:\n\"\"\"Replace the alter adds in the orig_profile with the new ones and return True if changed.\"\"\"\n        changed = False\n        if not profile.modify:\n            profile.modify = prof.Modify(alters=alters)\n            if alters:\n                changed = True\n        elif not profile.modify.alters:\n            profile.modify.alters = alters\n            if alters:\n                changed = True\n        else:\n            alter_dict = {}\n            # if an alter has adds - remove them up front and build dict of alters by control id\n            for alter in profile.modify.alters:\n                alter.adds = None\n                alter_dict[alter.control_id] = alter\n            # now go through new alters and add them to each control in dict by control id\n            ProfileAssemble._update_alter_adds(profile, alters, alter_dict)\n            # get the new list of alters from the dict and update profile\n            new_alters = list(alter_dict.values())\n            # special case, if all adds were deleted remove such alters completely\n            new_alters = list(filter(lambda alt: alt.adds or alt.removes, new_alters))\n            if profile.modify.alters != new_alters:\n                changed = True\n            profile.modify.alters = none_if_empty(new_alters)\n        return changed\n\n    @staticmethod\n    def _replace_modify_set_params(\n        profile: prof.Profile, param_dict: Dict[str, Any], param_map: Dict[str, str]\n    ) -> bool:\n\"\"\"\n        Replace the set_params in the profile with list and values from markdown.\n\n        Notes:\n            Returns whether or not change was made.\n        \"\"\"\n        changed = False\n        if param_dict:\n            if not profile.modify:\n                profile.modify = prof.Modify()\n            new_set_params: List[prof.SetParameter] = []\n            for key, sub_param_dict in param_dict.items():\n                if sub_param_dict:\n                    sub_param_dict['id'] = key\n                    param = ModelUtils.dict_to_parameter(sub_param_dict)\n                    new_set_params.append(\n                        prof.SetParameter(\n                            param_id=key,\n                            label=param.label,\n                            values=param.values,\n                            select=param.select,\n                            props=param.props\n                        )\n                    )\n            if profile.modify.set_parameters != new_set_params:\n                changed = True\n            # sort the params first by control sorting then by param_id\n            profile.modify.set_parameters = sorted(\n                new_set_params, key=lambda param: (param_map[param.param_id], param.param_id)\n            )\n        if profile.modify:\n            profile.modify.set_parameters = none_if_empty(profile.modify.set_parameters)\n        return changed\n\n    @staticmethod\n    def assemble_profile(\n        trestle_root: pathlib.Path,\n        parent_prof_name: str,\n        md_name: str,\n        assem_prof_name: str,\n        set_parameters_flag: bool,\n        regenerate: bool,\n        version: Optional[str],\n        sections_dict: Dict[str, str],\n        required_sections: List[str],\n        allowed_sections: Optional[List[str]]\n    ) -> int:\n\"\"\"\n        Assemble the markdown directory into a json profile model file.\n\n        Args:\n            trestle_root: The trestle root directory\n            parent_prof_name: Optional name of profile used to generate the markdown (default is assem_prof_name)\n            md_name: The name of the directory containing the markdown control files for the profile\n            assem_prof_name: The name of the assembled profile.  It can be the same as the parent to overwrite\n            set_parameters_flag: Use the params and props in yaml header to add or alter setparameters in the profile\n            regenerate: Whether to regenerate the uuid's in the profile\n            version: Optional version for the assembled profile\n            sections_dict: Optional map of short name to long name for sections\n            required_sections: List of required sections in assembled profile, as comma-separated short names\n            allowed_sections: Optional list of section short names that are allowed, as comma-separated short names\n\n        Returns:\n            0 on success, 1 otherwise\n\n        Notes:\n            There must already be a profile model and it will either be updated or a new json profile created.\n            The generated markdown has the current values for parameters of controls being imported, as set by\n            the original catalog and any intermediate profiles.  It also shows the current SetParameters being applied\n            by this profile.  That list of SetParameters can be edited by changing the assigned values and adding or\n            removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n            in the assembled profile if the --set-parameters option is specified.\n        \"\"\"\n        md_dir = trestle_root / md_name\n        if not md_dir.exists():\n            raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n        if not parent_prof_name:\n            parent_prof_name = assem_prof_name\n\n        parent_prof_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, parent_prof_name, prof.Profile)\n        if parent_prof_path is None:\n            raise TrestleError(f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.')\n\n        parent_prof, parent_prof_path = load_validate_model_name(trestle_root, parent_prof_name, prof.Profile)\n        new_content_type = FileContentType.path_to_content_type(parent_prof_path)\n\n        catalog = ProfileResolver.get_resolved_profile_catalog(\n            trestle_root, parent_prof_path, param_rep=ParameterRep.LEAVE_MOUSTACHE\n        )\n\n        context = ControlContext.generate(\n            ContextPurpose.PROFILE, to_markdown=False, trestle_root=trestle_root, md_root=md_dir\n        )\n        context.sections_dict = sections_dict\n        context.required_sections = required_sections\n\n        # load the editable sections of the markdown and create Adds for them\n        # then overwrite the Adds in the existing profile with the new ones\n        # keep track if any changes were made\n        catalog_api = CatalogAPI(catalog=catalog, context=context)\n        found_alters, param_dict, param_map = catalog_api.read_additional_content_from_md(label_as_key=True)\n\n        if allowed_sections is not None:\n            for bad_part in [\n                    part for alter in found_alters for add in as_list(alter.adds)\n                    for part in as_filtered_list(add.parts, lambda a: a.name not in allowed_sections)  # type: ignore\n            ]:\n                raise TrestleError(f'Profile has alter with name {bad_part.name} not in allowed sections.')\n\n        ProfileAssemble._replace_alter_adds(parent_prof, found_alters)\n        if set_parameters_flag:\n            ProfileAssemble._replace_modify_set_params(parent_prof, param_dict, param_map)\n\n        if version:\n            parent_prof.metadata.version = version\n\n        parent_prof.metadata.oscal_version = OSCAL_VERSION\n\n        assem_prof_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, assem_prof_name, prof.Profile, new_content_type\n        )\n\n        if assem_prof_path.exists():\n            _, _, existing_prof = ModelUtils.load_distributed(assem_prof_path, trestle_root)\n            if ModelUtils.models_are_equivalent(existing_prof, parent_prof):  # type: ignore\n                logger.info('Assembled profile is no different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n\n        if regenerate:\n            parent_prof, _, _ = ModelUtils.regenerate_uuids(parent_prof)\n        ModelUtils.update_last_modified(parent_prof)  # type: ignore\n\n        if assem_prof_path.parent.exists():\n            logger.info('Creating profile from markdown and destination profile exists, so updating.')\n            shutil.rmtree(str(assem_prof_path.parent))\n\n        assem_prof_path.parent.mkdir(parents=True, exist_ok=True)\n        parent_prof.oscal_write(assem_prof_path)  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble.assemble_profile","title":"assemble_profile(trestle_root, parent_prof_name, md_name, assem_prof_name, set_parameters_flag, regenerate, version, sections_dict, required_sections, allowed_sections) staticmethod","text":"

                                    Assemble the markdown directory into a json profile model file.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    The trestle root directory

                                    required parent_prof_name str

                                    Optional name of profile used to generate the markdown (default is assem_prof_name)

                                    required md_name str

                                    The name of the directory containing the markdown control files for the profile

                                    required assem_prof_name str

                                    The name of the assembled profile. It can be the same as the parent to overwrite

                                    required set_parameters_flag bool

                                    Use the params and props in yaml header to add or alter setparameters in the profile

                                    required regenerate bool

                                    Whether to regenerate the uuid's in the profile

                                    required version Optional[str]

                                    Optional version for the assembled profile

                                    required sections_dict Dict[str, str]

                                    Optional map of short name to long name for sections

                                    required required_sections List[str]

                                    List of required sections in assembled profile, as comma-separated short names

                                    required allowed_sections Optional[List[str]]

                                    Optional list of section short names that are allowed, as comma-separated short names

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success, 1 otherwise

                                    Notes

                                    There must already be a profile model and it will either be updated or a new json profile created. The generated markdown has the current values for parameters of controls being imported, as set by the original catalog and any intermediate profiles. It also shows the current SetParameters being applied by this profile. That list of SetParameters can be edited by changing the assigned values and adding or removing SetParameters from that list. During assembly that list will be used to create the SetParameters in the assembled profile if the --set-parameters option is specified.

                                    Source code in trestle/core/commands/author/prof.py
                                    @staticmethod\ndef assemble_profile(\n    trestle_root: pathlib.Path,\n    parent_prof_name: str,\n    md_name: str,\n    assem_prof_name: str,\n    set_parameters_flag: bool,\n    regenerate: bool,\n    version: Optional[str],\n    sections_dict: Dict[str, str],\n    required_sections: List[str],\n    allowed_sections: Optional[List[str]]\n) -> int:\n\"\"\"\n    Assemble the markdown directory into a json profile model file.\n\n    Args:\n        trestle_root: The trestle root directory\n        parent_prof_name: Optional name of profile used to generate the markdown (default is assem_prof_name)\n        md_name: The name of the directory containing the markdown control files for the profile\n        assem_prof_name: The name of the assembled profile.  It can be the same as the parent to overwrite\n        set_parameters_flag: Use the params and props in yaml header to add or alter setparameters in the profile\n        regenerate: Whether to regenerate the uuid's in the profile\n        version: Optional version for the assembled profile\n        sections_dict: Optional map of short name to long name for sections\n        required_sections: List of required sections in assembled profile, as comma-separated short names\n        allowed_sections: Optional list of section short names that are allowed, as comma-separated short names\n\n    Returns:\n        0 on success, 1 otherwise\n\n    Notes:\n        There must already be a profile model and it will either be updated or a new json profile created.\n        The generated markdown has the current values for parameters of controls being imported, as set by\n        the original catalog and any intermediate profiles.  It also shows the current SetParameters being applied\n        by this profile.  That list of SetParameters can be edited by changing the assigned values and adding or\n        removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n        in the assembled profile if the --set-parameters option is specified.\n    \"\"\"\n    md_dir = trestle_root / md_name\n    if not md_dir.exists():\n        raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n    if not parent_prof_name:\n        parent_prof_name = assem_prof_name\n\n    parent_prof_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, parent_prof_name, prof.Profile)\n    if parent_prof_path is None:\n        raise TrestleError(f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.')\n\n    parent_prof, parent_prof_path = load_validate_model_name(trestle_root, parent_prof_name, prof.Profile)\n    new_content_type = FileContentType.path_to_content_type(parent_prof_path)\n\n    catalog = ProfileResolver.get_resolved_profile_catalog(\n        trestle_root, parent_prof_path, param_rep=ParameterRep.LEAVE_MOUSTACHE\n    )\n\n    context = ControlContext.generate(\n        ContextPurpose.PROFILE, to_markdown=False, trestle_root=trestle_root, md_root=md_dir\n    )\n    context.sections_dict = sections_dict\n    context.required_sections = required_sections\n\n    # load the editable sections of the markdown and create Adds for them\n    # then overwrite the Adds in the existing profile with the new ones\n    # keep track if any changes were made\n    catalog_api = CatalogAPI(catalog=catalog, context=context)\n    found_alters, param_dict, param_map = catalog_api.read_additional_content_from_md(label_as_key=True)\n\n    if allowed_sections is not None:\n        for bad_part in [\n                part for alter in found_alters for add in as_list(alter.adds)\n                for part in as_filtered_list(add.parts, lambda a: a.name not in allowed_sections)  # type: ignore\n        ]:\n            raise TrestleError(f'Profile has alter with name {bad_part.name} not in allowed sections.')\n\n    ProfileAssemble._replace_alter_adds(parent_prof, found_alters)\n    if set_parameters_flag:\n        ProfileAssemble._replace_modify_set_params(parent_prof, param_dict, param_map)\n\n    if version:\n        parent_prof.metadata.version = version\n\n    parent_prof.metadata.oscal_version = OSCAL_VERSION\n\n    assem_prof_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, assem_prof_name, prof.Profile, new_content_type\n    )\n\n    if assem_prof_path.exists():\n        _, _, existing_prof = ModelUtils.load_distributed(assem_prof_path, trestle_root)\n        if ModelUtils.models_are_equivalent(existing_prof, parent_prof):  # type: ignore\n            logger.info('Assembled profile is no different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n\n    if regenerate:\n        parent_prof, _, _ = ModelUtils.regenerate_uuids(parent_prof)\n    ModelUtils.update_last_modified(parent_prof)  # type: ignore\n\n    if assem_prof_path.parent.exists():\n        logger.info('Creating profile from markdown and destination profile exists, so updating.')\n        shutil.rmtree(str(assem_prof_path.parent))\n\n    assem_prof_path.parent.mkdir(parents=True, exist_ok=True)\n    parent_prof.oscal_write(assem_prof_path)  # type: ignore\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate","title":" ProfileGenerate (AuthorCommonCommand) ","text":"

                                    Generate profile in markdown form from a profile in the trestle workspace.

                                    Source code in trestle/core/commands/author/prof.py
                                    class ProfileGenerate(AuthorCommonCommand):\n\"\"\"Generate profile in markdown form from a profile in the trestle workspace.\"\"\"\n\n    name = 'profile-generate'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the source profile model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument('-o', '--output', help=const.HELP_MARKDOWN_NAME, required=True, type=str)\n        self.add_argument('-y', '--yaml-header', help=const.HELP_YAML_PATH, required=False, type=str)\n        self.add_argument(\n            '-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true', default=False\n        )\n        self.add_argument(\n            '-ohv',\n            '--overwrite-header-values',\n            help=const.HELP_OVERWRITE_HEADER_VALUES,\n            required=False,\n            action='store_true',\n            default=False\n        )\n        self.add_argument('-s', '--sections', help=const.HELP_SECTIONS, required=False, type=str)\n        self.add_argument('-rs', '--required-sections', help=const.HELP_REQUIRED_SECTIONS, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root: pathlib.Path = args.trestle_root\n            if not file_utils.is_directory_name_allowed(args.output):\n                raise TrestleError(f'{args.output} is not an allowed directory name')\n\n            yaml_header: Dict[str, Any] = {}\n            if args.yaml_header:\n                try:\n                    logging.debug(f'Loading yaml header file {args.yaml_header}')\n                    yaml = YAML()\n                    yaml_header = yaml.load(pathlib.Path(args.yaml_header).open('r'))\n                except YAMLError as e:\n                    raise TrestleError(f'YAML error loading yaml header for ssp generation: {e}')\n\n            if args.force_overwrite:\n                try:\n                    logger.info(f'Overwriting the content in {args.output}.')\n                    clear_folder(pathlib.Path(args.output))\n                except TrestleError as e:  # pragma: no cover\n                    raise TrestleError(f'Unable to overwrite contents of {args.output}: {e}')\n\n            # combine command line sections with any in the yaml header, with priority to command line\n            sections_dict = comma_colon_sep_to_dict(args.sections)\n\n            profile_path = trestle_root / f'profiles/{args.name}/profile.json'\n\n            markdown_path = trestle_root / args.output\n\n            return self.generate_markdown(\n                trestle_root,\n                profile_path,\n                markdown_path,\n                yaml_header,\n                args.overwrite_header_values,\n                sections_dict,\n                comma_sep_to_list(args.required_sections)\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Generation of the profile markdown failed')\n\n    def generate_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        profile_path: pathlib.Path,\n        markdown_path: pathlib.Path,\n        yaml_header: Dict[str, Any],\n        overwrite_header_values: bool,\n        sections_dict: Optional[Dict[str, str]],\n        required_sections: Optional[List[str]]\n    ) -> int:\n\"\"\"Generate markdown for the controls in the profile.\n\n        Args:\n            trestle_root: Root directory of the trestle workspace\n            profile_path: Path of the profile json file\n            markdown_path: Path to the directory into which the markdown will be written\n            yaml_header: Dict to merge into the yaml header of the control markdown\n            overwrite_header_values: Overwrite values in the markdown header but allow new items to be added\n            sections_dict: Optional dict mapping section short names to long\n            required_sections: Optional list of sections that get prompted for prose if not in the profile\n\n        Returns:\n            0 on success, 1 on error\n        \"\"\"\n        try:\n            if sections_dict and const.STATEMENT in sections_dict:\n                logger.warning('statement is not allowed as a section name.')\n                return CmdReturnCodes.COMMAND_ERROR.value\n            _, _, profile = ModelUtils.load_distributed(profile_path, trestle_root)\n            catalog, inherited_props = ProfileResolver().get_resolved_profile_catalog_and_inherited_props(\n                trestle_root, profile_path, True, True, None, ParameterRep.LEAVE_MOUSTACHE\n            )\n\n            deep_set(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.TITLE], profile.metadata.title)\n\n            context = ControlContext.generate(ContextPurpose.PROFILE, True, trestle_root, markdown_path)\n            context.cli_yaml_header = yaml_header\n            context.sections_dict = sections_dict\n            context.profile = profile\n            context.overwrite_header_values = overwrite_header_values\n            context.set_parameters_flag = True\n            context.required_sections = required_sections\n            context.inherited_props = inherited_props\n            catalog_api = CatalogAPI(catalog=catalog, context=context)\n            catalog_api.write_catalog_as_markdown()\n\n        except TrestleNotFoundError as e:\n            raise TrestleError(f'Profile {profile_path} not found, error {e}')\n        except TrestleError as e:\n            raise TrestleError(f'Error generating the catalog as markdown: {e}')\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate.generate_markdown","title":"generate_markdown(self, trestle_root, profile_path, markdown_path, yaml_header, overwrite_header_values, sections_dict, required_sections)","text":"

                                    Generate markdown for the controls in the profile.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    Root directory of the trestle workspace

                                    required profile_path Path

                                    Path of the profile json file

                                    required markdown_path Path

                                    Path to the directory into which the markdown will be written

                                    required yaml_header Dict[str, Any]

                                    Dict to merge into the yaml header of the control markdown

                                    required overwrite_header_values bool

                                    Overwrite values in the markdown header but allow new items to be added

                                    required sections_dict Optional[Dict[str, str]]

                                    Optional dict mapping section short names to long

                                    required required_sections Optional[List[str]]

                                    Optional list of sections that get prompted for prose if not in the profile

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success, 1 on error

                                    Source code in trestle/core/commands/author/prof.py
                                    def generate_markdown(\n    self,\n    trestle_root: pathlib.Path,\n    profile_path: pathlib.Path,\n    markdown_path: pathlib.Path,\n    yaml_header: Dict[str, Any],\n    overwrite_header_values: bool,\n    sections_dict: Optional[Dict[str, str]],\n    required_sections: Optional[List[str]]\n) -> int:\n\"\"\"Generate markdown for the controls in the profile.\n\n    Args:\n        trestle_root: Root directory of the trestle workspace\n        profile_path: Path of the profile json file\n        markdown_path: Path to the directory into which the markdown will be written\n        yaml_header: Dict to merge into the yaml header of the control markdown\n        overwrite_header_values: Overwrite values in the markdown header but allow new items to be added\n        sections_dict: Optional dict mapping section short names to long\n        required_sections: Optional list of sections that get prompted for prose if not in the profile\n\n    Returns:\n        0 on success, 1 on error\n    \"\"\"\n    try:\n        if sections_dict and const.STATEMENT in sections_dict:\n            logger.warning('statement is not allowed as a section name.')\n            return CmdReturnCodes.COMMAND_ERROR.value\n        _, _, profile = ModelUtils.load_distributed(profile_path, trestle_root)\n        catalog, inherited_props = ProfileResolver().get_resolved_profile_catalog_and_inherited_props(\n            trestle_root, profile_path, True, True, None, ParameterRep.LEAVE_MOUSTACHE\n        )\n\n        deep_set(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.TITLE], profile.metadata.title)\n\n        context = ControlContext.generate(ContextPurpose.PROFILE, True, trestle_root, markdown_path)\n        context.cli_yaml_header = yaml_header\n        context.sections_dict = sections_dict\n        context.profile = profile\n        context.overwrite_header_values = overwrite_header_values\n        context.set_parameters_flag = True\n        context.required_sections = required_sections\n        context.inherited_props = inherited_props\n        catalog_api = CatalogAPI(catalog=catalog, context=context)\n        catalog_api.write_catalog_as_markdown()\n\n    except TrestleNotFoundError as e:\n        raise TrestleError(f'Profile {profile_path} not found, error {e}')\n    except TrestleError as e:\n        raise TrestleError(f'Error generating the catalog as markdown: {e}')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit","title":" ProfileInherit (AuthorCommonCommand) ","text":"

                                    Generate and populate profile in JSON from a parent profile and leveraged ssp in the trestle workspace.

                                    Source code in trestle/core/commands/author/prof.py
                                    class ProfileInherit(AuthorCommonCommand):\n\"\"\"Generate and populate profile in JSON from a parent profile and leveraged ssp in the trestle workspace.\"\"\"\n\n    name = 'profile-inherit'\n\n    def _init_arguments(self) -> None:\n        ssp_help_str = 'Name of the leveraged ssp model in the trestle workspace'\n        self.add_argument('-s', '--ssp', help=ssp_help_str, required=True, type=str)\n        profile_help_str = 'Name of the parent profile model in the trestle workspace'\n        self.add_argument('-p', '--profile', help=profile_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json Profile'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root: pathlib.Path = args.trestle_root\n\n            if args.profile and args.profile == args.output:\n                logger.warning(f'Output profile {args.output} cannot equal parent')\n                return CmdReturnCodes.INCORRECT_ARGS.value\n\n            return self.initialize_profile(\n                trestle_root=trestle_root,\n                parent_prof_name=args.profile,\n                output_prof_name=args.output,\n                leveraged_ssp_name=args.ssp,\n                version=args.version\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Profile generation failed')\n\n    @staticmethod\n    def _is_inherited(all_comps: List[ssp.ByComponent]) -> bool:\n        # Fail fast by checking for any non-compliant components.\n        # Must contain provided export statements, no responsibility\n        # statements, and be implemented.\n        for comp in all_comps:\n            if comp.export is None:\n                return False\n\n            if comp.export.responsibilities is not None:\n                return False\n\n            if comp.export.provided is None:\n                return False\n\n            if comp.implementation_status.state != const.STATUS_IMPLEMENTED:\n                return False\n\n        return True\n\n    @staticmethod\n    def _create_components_by_id(leveraged_ssp: ssp.SystemSecurityPlan) -> Dict[str, List[ssp.ByComponent]]:\n        components_by_id: Dict[str, List[ssp.ByComponent]] = {}\n        for implemented_requirement in leveraged_ssp.control_implementation.implemented_requirements:\n            by_components: List[ssp.ByComponent] = []\n            if implemented_requirement.by_components:\n                by_components.extend(implemented_requirement.by_components)\n            if implemented_requirement.statements:\n                for stm in implemented_requirement.statements:\n                    if stm.by_components:\n                        by_components.extend(stm.by_components)\n            components_by_id[implemented_requirement.control_id] = none_if_empty(by_components)\n        return components_by_id\n\n    @staticmethod\n    def update_profile_import(\n        orig_prof_import: prof.Import, leveraged_ssp: ssp.SystemSecurityPlan, catalog_api: CatalogAPI\n    ) -> None:\n\"\"\"Add controls to different sections of a profile import based on catalog and leveraged SSP.\n\n        Args:\n            orig_prof_import: The original profile import that will have the control selection updated.\n            leveraged_ssp: SSP input for control filtering\n            catalog_api: Catalog API with access to controls that need to be filtered\n\n        Returns:\n            None\n        \"\"\"\n        exclude_with_ids: Set[str] = set()\n\n        # Create dictionary containing all by-components by control for faster searching\n        components_by_id: Dict[str, List[ssp.ByComponent]] = ProfileInherit._create_components_by_id(leveraged_ssp)\n\n        # Looping by controls in the catalog because the ids in the profile should\n        # be a subset of the catalog and not the ssp controls.\n        catalog_control_ids: Set[str] = set(catalog_api._catalog_interface.get_control_ids())\n        for control_id in catalog_control_ids:\n\n            if control_id not in components_by_id:\n                continue\n\n            by_comps: Optional[List[ssp.ByComponent]] = components_by_id[control_id]\n            if by_comps is not None and ProfileInherit._is_inherited(by_comps):\n                exclude_with_ids.add(control_id)\n\n        include_with_ids: Set[str] = catalog_control_ids - exclude_with_ids\n\n        orig_prof_import.include_controls = [prof.SelectControl(with_ids=sorted(include_with_ids))]\n        orig_prof_import.exclude_controls = [prof.SelectControl(with_ids=sorted(exclude_with_ids))]\n\n    def initialize_profile(\n        self,\n        trestle_root: pathlib.Path,\n        parent_prof_name: str,\n        output_prof_name: str,\n        leveraged_ssp_name: str,\n        version: Optional[str],\n    ) -> int:\n\"\"\"Initialize profile with controls from a parent profile, filtering by inherited controls.\n\n        Args:\n            trestle_root: Root directory of the trestle workspace\n            parent_prof_name: Name of the parent profile in the trestle workspace\n            output_prof_name: Name of the output profile json file\n            leveraged_ssp_name: Name of the ssp in the trestle workspace for control filtering\n            version: Optional profile version\n\n        Returns:\n            0 on success, 1 on error\n\n        Notes:\n            The profile model will either be updated or a new json profile created. This will overwrite\n            any import information on an exiting profile, but will preserve control modifications and parameters.\n            Allowing profile updates ensure that SSP export updates can be incorporated into an existing profile. All\n            controls from the original profile will exists and will be grouped by included and excluded controls based\n            on inheritance information.\n        \"\"\"\n        try:\n            result_profile: prof.Profile\n            existing_profile: Optional[prof.Profile] = None\n\n            existing_profile_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, output_prof_name, prof.Profile\n            )\n\n            # If a profile exists at the output path, use that as a starting point for a new profile.\n            # else create a new sample profile.\n            if existing_profile_path is not None:\n                existing_profile, _ = load_validate_model_name(trestle_root,\n                                                               output_prof_name,\n                                                               prof.Profile,\n                                                               FileContentType.JSON)\n                result_profile = copy.deepcopy(existing_profile)\n            else:\n                result_profile = gens.generate_sample_model(prof.Profile)\n\n            parent_prof_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, parent_prof_name, prof.Profile\n            )\n            if parent_prof_path is None:\n                raise TrestleNotFoundError(\n                    f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.'\n                )\n\n            local_path = f'profiles/{parent_prof_name}/profile.json'\n            profile_import: prof.Import = gens.generate_sample_model(prof.Import)\n            profile_import.href = const.TRESTLE_HREF_HEADING + local_path\n\n            leveraged_ssp: ssp.SystemSecurityPlan\n            try:\n                leveraged_ssp, _ = load_validate_model_name(\n                    trestle_root,\n                    leveraged_ssp_name,\n                    ssp.SystemSecurityPlan,\n                    FileContentType.JSON\n                )\n            except TrestleNotFoundError as e:\n                raise TrestleError(f'SSP {leveraged_ssp_name} not found: {e}')\n\n            prof_resolver = ProfileResolver()\n            catalog = prof_resolver.get_resolved_profile_catalog(\n                trestle_root, parent_prof_path, show_value_warnings=True\n            )\n            catalog_api = CatalogAPI(catalog=catalog)\n\n            # Sort controls based on what controls in the SSP have exported provided information with no\n            # customer responsibility\n            ProfileInherit.update_profile_import(profile_import, leveraged_ssp, catalog_api)\n\n            result_profile.imports[0] = profile_import\n\n            if version:\n                result_profile.metadata.version = version\n\n            if ModelUtils.models_are_equivalent(existing_profile, result_profile):\n                logger.info('Profile is no different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n\n            ModelUtils.update_last_modified(result_profile)\n            ModelUtils.save_top_level_model(result_profile, trestle_root, output_prof_name, FileContentType.JSON)\n\n        except TrestleError as e:\n            raise TrestleError(f'Error initializing profile {output_prof_name}: {e}')\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit.initialize_profile","title":"initialize_profile(self, trestle_root, parent_prof_name, output_prof_name, leveraged_ssp_name, version)","text":"

                                    Initialize profile with controls from a parent profile, filtering by inherited controls.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    Root directory of the trestle workspace

                                    required parent_prof_name str

                                    Name of the parent profile in the trestle workspace

                                    required output_prof_name str

                                    Name of the output profile json file

                                    required leveraged_ssp_name str

                                    Name of the ssp in the trestle workspace for control filtering

                                    required version Optional[str]

                                    Optional profile version

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success, 1 on error

                                    Notes

                                    The profile model will either be updated or a new json profile created. This will overwrite any import information on an exiting profile, but will preserve control modifications and parameters. Allowing profile updates ensure that SSP export updates can be incorporated into an existing profile. All controls from the original profile will exists and will be grouped by included and excluded controls based on inheritance information.

                                    Source code in trestle/core/commands/author/prof.py
                                    def initialize_profile(\n    self,\n    trestle_root: pathlib.Path,\n    parent_prof_name: str,\n    output_prof_name: str,\n    leveraged_ssp_name: str,\n    version: Optional[str],\n) -> int:\n\"\"\"Initialize profile with controls from a parent profile, filtering by inherited controls.\n\n    Args:\n        trestle_root: Root directory of the trestle workspace\n        parent_prof_name: Name of the parent profile in the trestle workspace\n        output_prof_name: Name of the output profile json file\n        leveraged_ssp_name: Name of the ssp in the trestle workspace for control filtering\n        version: Optional profile version\n\n    Returns:\n        0 on success, 1 on error\n\n    Notes:\n        The profile model will either be updated or a new json profile created. This will overwrite\n        any import information on an exiting profile, but will preserve control modifications and parameters.\n        Allowing profile updates ensure that SSP export updates can be incorporated into an existing profile. All\n        controls from the original profile will exists and will be grouped by included and excluded controls based\n        on inheritance information.\n    \"\"\"\n    try:\n        result_profile: prof.Profile\n        existing_profile: Optional[prof.Profile] = None\n\n        existing_profile_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, output_prof_name, prof.Profile\n        )\n\n        # If a profile exists at the output path, use that as a starting point for a new profile.\n        # else create a new sample profile.\n        if existing_profile_path is not None:\n            existing_profile, _ = load_validate_model_name(trestle_root,\n                                                           output_prof_name,\n                                                           prof.Profile,\n                                                           FileContentType.JSON)\n            result_profile = copy.deepcopy(existing_profile)\n        else:\n            result_profile = gens.generate_sample_model(prof.Profile)\n\n        parent_prof_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, parent_prof_name, prof.Profile\n        )\n        if parent_prof_path is None:\n            raise TrestleNotFoundError(\n                f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.'\n            )\n\n        local_path = f'profiles/{parent_prof_name}/profile.json'\n        profile_import: prof.Import = gens.generate_sample_model(prof.Import)\n        profile_import.href = const.TRESTLE_HREF_HEADING + local_path\n\n        leveraged_ssp: ssp.SystemSecurityPlan\n        try:\n            leveraged_ssp, _ = load_validate_model_name(\n                trestle_root,\n                leveraged_ssp_name,\n                ssp.SystemSecurityPlan,\n                FileContentType.JSON\n            )\n        except TrestleNotFoundError as e:\n            raise TrestleError(f'SSP {leveraged_ssp_name} not found: {e}')\n\n        prof_resolver = ProfileResolver()\n        catalog = prof_resolver.get_resolved_profile_catalog(\n            trestle_root, parent_prof_path, show_value_warnings=True\n        )\n        catalog_api = CatalogAPI(catalog=catalog)\n\n        # Sort controls based on what controls in the SSP have exported provided information with no\n        # customer responsibility\n        ProfileInherit.update_profile_import(profile_import, leveraged_ssp, catalog_api)\n\n        result_profile.imports[0] = profile_import\n\n        if version:\n            result_profile.metadata.version = version\n\n        if ModelUtils.models_are_equivalent(existing_profile, result_profile):\n            logger.info('Profile is no different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n\n        ModelUtils.update_last_modified(result_profile)\n        ModelUtils.save_top_level_model(result_profile, trestle_root, output_prof_name, FileContentType.JSON)\n\n    except TrestleError as e:\n        raise TrestleError(f'Error initializing profile {output_prof_name}: {e}')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit.update_profile_import","title":"update_profile_import(orig_prof_import, leveraged_ssp, catalog_api) staticmethod","text":"

                                    Add controls to different sections of a profile import based on catalog and leveraged SSP.

                                    Parameters:

                                    Name Type Description Default orig_prof_import Import

                                    The original profile import that will have the control selection updated.

                                    required leveraged_ssp SystemSecurityPlan

                                    SSP input for control filtering

                                    required catalog_api CatalogAPI

                                    Catalog API with access to controls that need to be filtered

                                    required

                                    Returns:

                                    Type Description None

                                    None

                                    Source code in trestle/core/commands/author/prof.py
                                    @staticmethod\ndef update_profile_import(\n    orig_prof_import: prof.Import, leveraged_ssp: ssp.SystemSecurityPlan, catalog_api: CatalogAPI\n) -> None:\n\"\"\"Add controls to different sections of a profile import based on catalog and leveraged SSP.\n\n    Args:\n        orig_prof_import: The original profile import that will have the control selection updated.\n        leveraged_ssp: SSP input for control filtering\n        catalog_api: Catalog API with access to controls that need to be filtered\n\n    Returns:\n        None\n    \"\"\"\n    exclude_with_ids: Set[str] = set()\n\n    # Create dictionary containing all by-components by control for faster searching\n    components_by_id: Dict[str, List[ssp.ByComponent]] = ProfileInherit._create_components_by_id(leveraged_ssp)\n\n    # Looping by controls in the catalog because the ids in the profile should\n    # be a subset of the catalog and not the ssp controls.\n    catalog_control_ids: Set[str] = set(catalog_api._catalog_interface.get_control_ids())\n    for control_id in catalog_control_ids:\n\n        if control_id not in components_by_id:\n            continue\n\n        by_comps: Optional[List[ssp.ByComponent]] = components_by_id[control_id]\n        if by_comps is not None and ProfileInherit._is_inherited(by_comps):\n            exclude_with_ids.add(control_id)\n\n    include_with_ids: Set[str] = catalog_control_ids - exclude_with_ids\n\n    orig_prof_import.include_controls = [prof.SelectControl(with_ids=sorted(include_with_ids))]\n    orig_prof_import.exclude_controls = [prof.SelectControl(with_ids=sorted(exclude_with_ids))]\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve","title":" ProfileResolve (AuthorCommonCommand) ","text":"

                                    Resolve profile to resolved profile catalog.

                                    Source code in trestle/core/commands/author/prof.py
                                    class ProfileResolve(AuthorCommonCommand):\n\"\"\"Resolve profile to resolved profile catalog.\"\"\"\n\n    name = 'profile-resolve'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the source profile model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument('-o', '--output', help='Name of the output resolved profile catalog', required=True, type=str)\n        self.add_argument(\n            '-sv',\n            '--show-values',\n            help='Show values for parameters in prose',\n            required=False,\n            action='store_true',\n            default=False\n        )\n        self.add_argument(\n            '-sl',\n            '--show-labels',\n            help='Show labels for parameters in prose instead of values',\n            required=False,\n            action='store_true',\n            default=False\n        )\n        self.add_argument(\n            '-bf',\n            '--bracket-format',\n            help='With -sv, allows brackets around value, e.g. [.] or ((.)), with the dot representing the value.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-vap',\n            '--value-assigned-prefix',\n            help='With -sv, places a prefix in front of the parameter string if a value has been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-vnap',\n            '--value-not-assigned-prefix',\n            help='With -sv, places a prefix in front of the parameter string if a value has *not* been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-lp',\n            '--label-prefix',\n            help='With -sl, places a prefix in front of the parameter label.',\n            required=False,\n            type=str,\n            default=''\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root: pathlib.Path = args.trestle_root\n            profile_path = trestle_root / f'profiles/{args.name}/profile.json'\n            catalog_name = args.output\n            show_values = args.show_values\n            param_format = args.bracket_format\n            value_assigned_prefix = args.value_assigned_prefix\n            value_not_assigned_prefix = args.value_not_assigned_prefix\n            label_prefix = args.label_prefix\n            show_labels = args.show_labels\n\n            return self.resolve_profile(\n                trestle_root,\n                profile_path,\n                catalog_name,\n                show_values,\n                param_format,\n                value_assigned_prefix,\n                value_not_assigned_prefix,\n                show_labels,\n                label_prefix\n            )\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Generation of the resolved profile catalog failed')\n\n    def resolve_profile(\n        self,\n        trestle_root: pathlib.Path,\n        profile_path: pathlib.Path,\n        catalog_name: str,\n        show_values: bool,\n        bracket_format: str,\n        value_assigned_prefix: Optional[str],\n        value_not_assigned_prefix: Optional[str],\n        show_labels: bool,\n        label_prefix: Optional[str]\n    ) -> int:\n\"\"\"Create resolved profile catalog from given profile.\n\n        Args:\n            trestle_root: Root directory of the trestle workspace\n            profile_path: Path of the profile json file\n            catalog_name: Name of the resolved profile catalog\n            show_values: If true, show values of parameters in prose rather than original {{}} form\n            bracket_format: String representing brackets around value, e.g. [.] or ((.))\n            value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n            value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n            show_labels: Show labels for parameters and not values\n            label_prefix: Prefix placed in front of param label\n\n        Returns:\n            0 on success and raises exception on error\n        \"\"\"\n        if not profile_path.exists():\n            raise TrestleNotFoundError(f'Cannot resolve profile catalog: profile {profile_path} does not exist.')\n\n        param_rep = ParameterRep.LEAVE_MOUSTACHE\n        if show_values:\n            param_rep = ParameterRep.ASSIGNMENT_FORM\n            if label_prefix or show_labels:\n                raise TrestleError('Use of show-values is not compatible with show-labels or label-prefix')\n        elif value_assigned_prefix or value_not_assigned_prefix:\n            raise TrestleError('Use of value-assigned-prefix or value-not-assigned-prefix requires show-values')\n        if show_labels:\n            param_rep = ParameterRep.LABEL_FORM\n            # overload value_not_assigned_prefix to use the label_prefix value\n            value_not_assigned_prefix = label_prefix\n        elif label_prefix:\n            raise TrestleError('Use of label-prefix requires show-labels')\n\n        bracket_format = none_if_empty(bracket_format)\n        catalog = ProfileResolver().get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            False,\n            False,\n            bracket_format,\n            param_rep,\n            False,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        ModelUtils.save_top_level_model(catalog, trestle_root, catalog_name, FileContentType.JSON)\n\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve.resolve_profile","title":"resolve_profile(self, trestle_root, profile_path, catalog_name, show_values, bracket_format, value_assigned_prefix, value_not_assigned_prefix, show_labels, label_prefix)","text":"

                                    Create resolved profile catalog from given profile.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    Root directory of the trestle workspace

                                    required profile_path Path

                                    Path of the profile json file

                                    required catalog_name str

                                    Name of the resolved profile catalog

                                    required show_values bool

                                    If true, show values of parameters in prose rather than original {{}} form

                                    required bracket_format str

                                    String representing brackets around value, e.g. [.] or ((.))

                                    required value_assigned_prefix Optional[str]

                                    Prefix placed in front of param string if a value was assigned

                                    required value_not_assigned_prefix Optional[str]

                                    Prefix placed in front of param string if a value was not assigned

                                    required show_labels bool

                                    Show labels for parameters and not values

                                    required label_prefix Optional[str]

                                    Prefix placed in front of param label

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success and raises exception on error

                                    Source code in trestle/core/commands/author/prof.py
                                    def resolve_profile(\n    self,\n    trestle_root: pathlib.Path,\n    profile_path: pathlib.Path,\n    catalog_name: str,\n    show_values: bool,\n    bracket_format: str,\n    value_assigned_prefix: Optional[str],\n    value_not_assigned_prefix: Optional[str],\n    show_labels: bool,\n    label_prefix: Optional[str]\n) -> int:\n\"\"\"Create resolved profile catalog from given profile.\n\n    Args:\n        trestle_root: Root directory of the trestle workspace\n        profile_path: Path of the profile json file\n        catalog_name: Name of the resolved profile catalog\n        show_values: If true, show values of parameters in prose rather than original {{}} form\n        bracket_format: String representing brackets around value, e.g. [.] or ((.))\n        value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n        value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n        show_labels: Show labels for parameters and not values\n        label_prefix: Prefix placed in front of param label\n\n    Returns:\n        0 on success and raises exception on error\n    \"\"\"\n    if not profile_path.exists():\n        raise TrestleNotFoundError(f'Cannot resolve profile catalog: profile {profile_path} does not exist.')\n\n    param_rep = ParameterRep.LEAVE_MOUSTACHE\n    if show_values:\n        param_rep = ParameterRep.ASSIGNMENT_FORM\n        if label_prefix or show_labels:\n            raise TrestleError('Use of show-values is not compatible with show-labels or label-prefix')\n    elif value_assigned_prefix or value_not_assigned_prefix:\n        raise TrestleError('Use of value-assigned-prefix or value-not-assigned-prefix requires show-values')\n    if show_labels:\n        param_rep = ParameterRep.LABEL_FORM\n        # overload value_not_assigned_prefix to use the label_prefix value\n        value_not_assigned_prefix = label_prefix\n    elif label_prefix:\n        raise TrestleError('Use of label-prefix requires show-labels')\n\n    bracket_format = none_if_empty(bracket_format)\n    catalog = ProfileResolver().get_resolved_profile_catalog(\n        trestle_root,\n        profile_path,\n        False,\n        False,\n        bracket_format,\n        param_rep,\n        False,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    ModelUtils.save_top_level_model(catalog, trestle_root, catalog_name, FileContentType.JSON)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.ssp/","title":"ssp","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp","title":"trestle.core.commands.author.ssp","text":"

                                    Create ssp from catalog and profile.

                                    "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPAssemble","title":" SSPAssemble (AuthorCommonCommand) ","text":"

                                    Assemble markdown files of controls into an SSP json file.

                                    Source code in trestle/core/commands/author/ssp.py
                                    class SSPAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into an SSP json file.\"\"\"\n\n    name = 'ssp-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the ssp model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the input markdown file directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json SSP'\n        self.add_argument('-cd', '--compdefs', help=const.HELP_COMPDEFS, required=False, type=str)\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    @staticmethod\n    def _get_ssp_component(ssp: ossp.SystemSecurityPlan, gen_comp: generic.GenericComponent) -> ossp.SystemComponent:\n        for component in as_list(ssp.system_implementation.components):\n            if component.title == gen_comp.title:\n                return component\n        # if this is a new system component assign its status as operational by default\n        # the status of the system components are not stored in the markdown\n        gen_comp.status.state = const.STATUS_OPERATIONAL\n        new_component = gen_comp.as_system_component()\n        return new_component\n\n    @staticmethod\n    def _merge_by_comps(stat: ossp.Statement, statement: ossp.Statement, set_params: List[ossp.SetParameter]) -> None:\n        for by_comp in as_list(statement.by_components):\n            found = False\n            for dest_by_comp in as_list(stat.by_components):\n                if dest_by_comp.component_uuid == by_comp.component_uuid:\n                    dest_by_comp.description = by_comp.description\n                    dest_by_comp.props = as_list(dest_by_comp.props)\n                    dest_by_comp.props.extend(as_list(statement.props))\n                    dest_by_comp.props = none_if_empty(ControlInterface.clean_props(by_comp.props))\n                    dest_by_comp.implementation_status = by_comp.implementation_status\n                    dest_by_comp.set_parameters = none_if_empty(set_params)\n                    found = True\n                    break\n            if not found:\n                stat.by_components = as_list(stat.by_components)\n                by_comp.set_parameters = none_if_empty(set_params)\n                stat.by_components.append(by_comp)\n\n    @staticmethod\n    def _merge_statement(\n        imp_req: ossp.ImplementedRequirement,\n        statement: generic.GenericStatement,\n        set_params: List[ossp.SetParameter],\n    ) -> None:\n\"\"\"Merge the generic statement into the statements of the imp_req.\"\"\"\n        # if the statement id is already in the imp_req, merge its by_comps into the existing statement\n        for stat in as_list(imp_req.statements):\n            if stat.statement_id == statement.statement_id:\n                SSPAssemble._merge_by_comps(stat, statement, set_params)\n                return\n        # otherwise just ad the statement - but only if it has by_comps\n        if statement.by_components:\n            imp_req.statements = as_list(imp_req.statements)\n            imp_req.statements.append(statement)\n\n    @staticmethod\n    def _merge_imp_req_into_imp_req(\n        imp_req: ossp.ImplementedRequirement,\n        gen_imp_req: generic.GenericImplementedRequirement,\n        set_params: List[ossp.SetParameter]\n    ) -> None:\n\"\"\"Merge comp def imp req into existing imp req.\"\"\"\n        # convert generic imp req from comp defs into ssp form\n        src_imp_req = gen_imp_req.as_ssp()\n        imp_req.props = none_if_empty(\n            ControlInterface.clean_props(gen_imp_req.props, remove_imp_status=True, remove_all_rule_info=True)\n        )\n        for statement in as_list(src_imp_req.statements):\n            SSPAssemble._merge_statement(imp_req, statement, set_params)\n\n    @staticmethod\n    def _get_params_for_rules(context: ControlContext, rules_list: List[str],\n                              set_params: List[ossp.SetParameter]) -> List[ossp.SetParameter]:\n\"\"\"Get all set_params needed by the rules along with non-rule set_params.\"\"\"\n        needed_param_ids: Set[str] = set()\n        rule_dict = context.rules_params_dict.get(context.comp_name, {})\n        # find param_ids needed by rules\n        for rule_id in rules_list:\n            # get list of param_ids associated with this rule_id\n            param_ids = [\n                param['name'] for params in rule_dict.values() for param in params if param['rule-id'] == rule_id\n            ]\n            needed_param_ids.update(param_ids)\n        all_rule_param_ids = [param['name'] for params in rule_dict.values() for param in params]\n        # any set_param that isn't associated with a rule should be included as a normal control set param with no rule\n        for set_param in set_params:\n            if set_param.param_id not in all_rule_param_ids:\n                needed_param_ids.add(set_param.param_id)\n        param_ids_list = sorted(needed_param_ids)\n        needed_set_params: List[ossp.SetParameter] = []\n        for param_id in param_ids_list:\n            set_param = None\n            for sp in set_params:\n                if sp.param_id == param_id:\n                    set_param = sp\n                    break\n            if set_param:\n                needed_set_params.append(set_param)\n            else:\n                logger.warning(f'No set param found for param {param_id}')\n        return needed_set_params\n\n    @staticmethod\n    def _add_imp_req_to_ssp(\n        ssp: ossp.SystemSecurityPlan,\n        gen_comp: generic.GenericComponent,\n        gen_imp_req: generic.GenericImplementedRequirement,\n        set_params: List[ossp.SetParameter],\n        context: ControlContext\n    ) -> None:\n\"\"\"Add imp req from control implementation into new ssp being assembled.\"\"\"\n        # the incoming gen_imp_req comes directly from the comp def\n        # but the imp_req here is pulled from the ssp and created if not already there\n        imp_req = CatalogReader._get_imp_req_for_control(ssp, gen_imp_req.control_id)\n        local_set_params = as_list(set_params)[:]\n        local_set_params.extend(as_list(imp_req.set_parameters))\n        local_set_params = ControlInterface.uniquify_set_params(local_set_params)\n        # get any rules set at control level, if present\n        rules_list, _ = ControlInterface.get_rule_list_for_item(gen_imp_req)  # type: ignore\n        # There should be no rule content at top level of imp_req in ssp so strip them out\n        imp_req.props = none_if_empty(\n            ControlInterface.clean_props(gen_imp_req.props, remove_imp_status=True, remove_all_rule_info=True)\n        )\n        # if we have rules applying or need to make set_params, we need to make a by_comp\n        control_set_params = SSPAssemble._get_params_for_rules(context, rules_list, local_set_params)\n        if rules_list or control_set_params:\n            by_comp = gens.generate_sample_model(ossp.ByComponent)\n            by_comp.component_uuid = gen_comp.uuid\n            by_comp.description = gen_imp_req.description\n            by_comp.set_parameters = none_if_empty(control_set_params)\n            by_comp.implementation_status = ControlInterface.get_status_from_props(gen_imp_req)  # type: ignore\n            by_comp.props = none_if_empty(ControlInterface.clean_props(gen_imp_req.props))\n            imp_req.by_components = as_list(imp_req.by_components)\n            imp_req.by_components.append(by_comp)\n        # each statement in ci corresponds to by_comp in an ssp imp req\n        # so insert the new by_comp directly into the ssp, generating parts as needed\n        imp_req.statements = as_list(imp_req.statements)\n        for statement in as_list(gen_imp_req.statements):\n            if ControlInterface.item_has_rules(statement):  # type: ignore\n                imp_req = CatalogReader._get_imp_req_for_statement(ssp, gen_imp_req.control_id, statement.statement_id)\n                by_comp = CatalogReader._get_by_comp_from_imp_req(imp_req, statement.statement_id, gen_comp.uuid)\n                by_comp.description = statement.description\n                by_comp.props = none_if_empty(ControlInterface.clean_props(statement.props))\n                rules_list, _ = ControlInterface.get_rule_list_for_item(statement)  # type: ignore\n                by_comp.set_parameters = none_if_empty(\n                    SSPAssemble._get_params_for_rules(context, rules_list, local_set_params)\n                )\n        imp_req.statements = none_if_empty(imp_req.statements)\n        ssp.control_implementation.implemented_requirements = as_list(\n            ssp.control_implementation.implemented_requirements\n        )\n\n    @staticmethod\n    def _merge_imp_req_into_ssp(\n        ssp: ossp.SystemSecurityPlan,\n        gen_imp_req: generic.GenericImplementedRequirement,\n        set_params: List[ossp.SetParameter],\n    ) -> None:\n\"\"\"Merge the new imp_reqs into the ssp.\"\"\"\n        for imp_req in as_list(ssp.control_implementation.implemented_requirements):\n            if imp_req.control_id == gen_imp_req.control_id:\n                SSPAssemble._merge_imp_req_into_imp_req(imp_req, gen_imp_req, set_params)\n                return\n        new_imp_req = gen_imp_req.as_ssp()\n        imp_req.props = none_if_empty(\n            ControlInterface.clean_props(gen_imp_req.props, remove_imp_status=True, remove_all_rule_info=True)\n        )\n        ssp.control_implementation.implemented_requirements.append(new_imp_req)\n\n    def _merge_comp_defs(\n        self,\n        ssp: ossp.SystemSecurityPlan,\n        comp_dict: Dict[str, generic.GenericComponent],\n        context: ControlContext,\n        catalog_interface: CatalogInterface\n    ) -> None:\n\"\"\"Merge the original generic comp defs into the ssp.\"\"\"\n        all_comps: List[ossp.SystemComponent] = []\n        # determine if this is a new and empty ssp\n        new_ssp = not ssp.control_implementation.implemented_requirements\n        for _, gen_comp in comp_dict.items():\n            context.comp_name = gen_comp.title\n            all_ci_props: List[com.Property] = []\n            ssp_comp = SSPAssemble._get_ssp_component(ssp, gen_comp)\n            set_params: List[ossp.SetParameter] = []\n            for ci in as_list(gen_comp.control_implementations):\n                all_ci_props.extend(as_list(ci.props))\n                # get the list of set_params in the control implementation - for this component\n                for sp in as_list(ci.set_parameters):\n                    set_params.append(sp.to_ssp())\n                for imp_req in as_list(ci.implemented_requirements):\n                    # ignore any controls not in the ssp profile (resolved catalog)\n                    if not catalog_interface.get_control(imp_req.control_id):\n                        logger.debug(f'Ignoring imp_req for control {imp_req.control_id} not in ssp profile')\n                        continue\n                    if new_ssp:\n                        SSPAssemble._add_imp_req_to_ssp(ssp, gen_comp, imp_req, set_params, context)\n                    else:\n                        # compile all new uuids for new component definitions\n                        comp_uuids = [x.uuid for x in comp_dict.values()]\n                        for imp_requirement in as_list(ssp.control_implementation.implemented_requirements):\n                            to_delete = []\n                            for i, by_comp in enumerate(imp_requirement.by_components):\n                                if by_comp.component_uuid not in comp_uuids:\n                                    logger.warning(\n                                        f'By_component {by_comp.component_uuid} removed from implemented requirement '\n                                        f'{imp_requirement.control_id} because the corresponding component is not in '\n                                        'the specified compdefs '\n                                    )\n                                    to_delete.append(i)\n                            if to_delete:\n                                delete_list_from_list(imp_requirement.by_components, to_delete)\n                        SSPAssemble._merge_imp_req_into_ssp(ssp, imp_req, set_params)\n            ssp_comp.props = as_list(gen_comp.props)\n            ssp_comp.props.extend(all_ci_props)\n            ssp_comp.props = none_if_empty(ControlInterface.clean_props(ssp_comp.props))\n            all_comps.append(ssp_comp)\n\n        ssp.system_implementation.components = none_if_empty(all_comps)\n\n    def _generate_roles_in_metadata(self, ssp: ossp.SystemSecurityPlan) -> bool:\n\"\"\"Find all roles referenced by imp reqs and create role in metadata as needed.\"\"\"\n        metadata = ssp.metadata\n        metadata.roles = as_list(metadata.roles)\n        known_role_ids = [role.id for role in metadata.roles]\n        changed = False\n        for imp_req in ssp.control_implementation.implemented_requirements:\n            role_ids = [resp_role.role_id for resp_role in as_list(imp_req.responsible_roles)]\n            for role_id in role_ids:\n                if role_id not in known_role_ids:\n                    role = com.Role(id=role_id, title=role_id)\n                    metadata.roles.append(role)\n                    known_role_ids.append(role_id)\n                    changed = True\n        metadata.roles = none_if_empty(metadata.roles)\n        return changed\n\n    @staticmethod\n    def _build_comp_dict_from_comp_defs(\n        trestle_root: pathlib.Path, comp_def_name_list: List[str], create_sys_comp: bool\n    ) -> Dict[str, generic.GenericComponent]:\n        comp_dict: Dict[str, generic.GenericComponent] = {}\n        for comp_name in comp_def_name_list:\n            comp_def, _ = ModelUtils.load_model_for_class(trestle_root, comp_name, comp.ComponentDefinition)\n            for def_comp in as_list(comp_def.components):\n                gen_def_comp = generic.GenericComponent.from_defined_component(def_comp)\n                comp_dict[def_comp.title] = gen_def_comp\n        if create_sys_comp:\n            sys_comp = generic.GenericComponent.generate()\n            sys_comp.type = const.THIS_SYSTEM_AS_KEY\n            sys_comp.title = const.SSP_MAIN_COMP_NAME\n            comp_dict[sys_comp.title] = sys_comp\n        return comp_dict\n\n    @staticmethod\n    def _get_this_system_as_gen_comp(ssp: ossp.SystemSecurityPlan) -> Optional[generic.GenericComponent]:\n        for component in as_list(ssp.system_implementation.components):\n            if component.title == const.SSP_MAIN_COMP_NAME:\n                return generic.GenericComponent.from_defined_component(component)\n        return None\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n\n            md_path = trestle_root / args.markdown\n\n            # the original, reference ssp name defaults to same as output if name not specified\n            # thus in cyclic editing you are reading and writing same json ssp\n            orig_ssp_name = args.output\n            if args.name:\n                orig_ssp_name = args.name\n            new_ssp_name = args.output\n\n            _, profile_href = ComponentAssemble._get_profile_title_and_href_from_dir(md_path)\n            res_cat = ProfileResolver.get_resolved_profile_catalog(\n                trestle_root, profile_href, param_rep=ParameterRep.LEAVE_MOUSTACHE\n            )\n            catalog_interface = CatalogInterface(res_cat)\n\n            new_file_content_type = FileContentType.JSON\n\n            # if output ssp already exists, load it to see if new one is different\n            existing_ssp: Optional[ossp.SystemSecurityPlan] = None\n            new_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, new_ssp_name, ossp.SystemSecurityPlan\n            )\n            if new_ssp_path:\n                _, _, existing_ssp = ModelUtils.load_distributed(new_ssp_path, trestle_root)\n                new_file_content_type = FileContentType.path_to_content_type(new_ssp_path)\n\n            ssp: ossp.SystemSecurityPlan\n\n            # if orig ssp exists - need to load it rather than instantiate new one\n            orig_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, orig_ssp_name, ossp.SystemSecurityPlan\n            )\n\n            context = ControlContext.generate(ContextPurpose.SSP, True, trestle_root, md_path)\n            context.comp_def_name_list = comma_sep_to_list(args.compdefs)\n            part_id_map_by_id = catalog_interface.get_statement_part_id_map(False)\n            catalog_interface.generate_control_rule_info(part_id_map_by_id, context)\n\n            # load all original comp defs\n            # only additions from markdown will be imp_req prose and status\n            # and param vals\n            # if this is a new ssp then create system component in the comp_dict\n            comp_dict = SSPAssemble._build_comp_dict_from_comp_defs(\n                trestle_root, context.comp_def_name_list, not orig_ssp_path\n            )\n\n            part_id_map_by_label = catalog_interface.get_statement_part_id_map(True)\n\n            # if ssp already exists use it as container for new content\n            if orig_ssp_path:\n                # load the existing json ssp\n                _, _, ssp = ModelUtils.load_distributed(orig_ssp_path, trestle_root)\n                # add the This System comp to the comp dict so its uuid is known\n                sys_comp = SSPAssemble._get_this_system_as_gen_comp(ssp)\n                if not sys_comp:\n                    raise TrestleError('Original ssp has no system component.')\n                comp_dict[const.SSP_MAIN_COMP_NAME] = sys_comp\n\n                ssp_sys_imp_comps = ssp.system_implementation.components\n                # Gather the leveraged components to add back after the merge\n                leveraged_comps: Dict[str, ossp.SystemComponent] = {}\n                for sys_comp in ssp_sys_imp_comps:\n                    if sys_comp.props is not None:\n                        prop_names = [x.name for x in sys_comp.props]\n                        if const.LEV_AUTH_UUID in prop_names:\n                            leveraged_comps[sys_comp.title] = sys_comp\n\n                # Verifies older compdefs in an ssp no longer exist in newly provided ones\n                comp_titles = [x.title for x in comp_dict.values()]\n                diffs = [x for x in ssp_sys_imp_comps if x.title not in comp_titles and x.title not in leveraged_comps]\n                if diffs:\n                    for diff in diffs:\n                        logger.warning(\n                            f'Component named: {diff.title} was removed from system components from ssp '\n                            'because the corresponding component is not in '\n                            'the specified compdefs '\n                        )\n                    index_list = [ssp_sys_imp_comps.index(value) for value in diffs if value in ssp_sys_imp_comps]\n                    delete_list_from_list(ssp.system_implementation.components, index_list)\n\n                self._merge_comp_defs(ssp, comp_dict, context, catalog_interface)\n                CatalogReader.read_ssp_md_content(md_path, ssp, comp_dict, part_id_map_by_label, context)\n\n                new_file_content_type = FileContentType.path_to_content_type(orig_ssp_path)\n\n                # Add the leveraged comps back to the final ssp\n                ssp.system_implementation.components.extend(list(leveraged_comps.values()))\n            else:\n                # create a sample ssp to hold all the parts\n                ssp = gens.generate_sample_model(ossp.SystemSecurityPlan)\n                ssp.control_implementation.implemented_requirements = []\n                ssp.control_implementation.description = const.SSP_SYSTEM_CONTROL_IMPLEMENTATION_TEXT\n                ssp.system_implementation.components = []\n                self._merge_comp_defs(ssp, comp_dict, context, catalog_interface)\n                CatalogReader.read_ssp_md_content(md_path, ssp, comp_dict, part_id_map_by_label, context)\n\n                import_profile: ossp.ImportProfile = gens.generate_sample_model(ossp.ImportProfile)\n                import_profile.href = const.REPLACE_ME\n                ssp.import_profile = import_profile\n\n            # now that we know the complete list of needed components, add them to the sys_imp\n            # TODO if the ssp already existed then components may need to be removed if not ref'd by imp_reqs\n            self._generate_roles_in_metadata(ssp)\n\n            # If this is a leveraging SSP, update it with the retrieved exports from the leveraged SSP\n            inheritance_markdown_path = md_path.joinpath(const.INHERITANCE_VIEW_DIR)\n            if os.path.exists(inheritance_markdown_path):\n                SSPInheritanceAPI(inheritance_markdown_path, trestle_root).update_ssp_inheritance(ssp)\n\n            ssp.import_profile.href = profile_href\n\n            if args.version:\n                ssp.metadata.version = args.version\n\n            if ModelUtils.models_are_equivalent(existing_ssp, ssp):\n                logger.info('No changes to assembled ssp so ssp not written out.')\n                return CmdReturnCodes.SUCCESS.value\n\n            if args.regenerate:\n                ssp, _, _ = ModelUtils.regenerate_uuids(ssp)\n            ModelUtils.update_last_modified(ssp)\n            # validate model rules before saving\n            args_validate = argparse.Namespace(mode=const.VAL_MODE_RULES)\n            validator: Validator = validator_factory.get(args_validate)\n            if not validator.model_is_valid(ssp, True, trestle_root):\n                logger.error(\n                    'Validation of file to be imported did not pass. Rule parameter values validation failed, '\n                    'please check values are correct for shared parameters in current model'\n                )\n                return CmdReturnCodes.COMMAND_ERROR.value\n            # write out the ssp as json\n            ModelUtils.save_top_level_model(ssp, trestle_root, new_ssp_name, new_file_content_type)\n\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while assembling SSP')\n
                                    "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter","title":" SSPFilter (AuthorCommonCommand) ","text":"

                                    Filter the controls in an ssp.

                                    The filtered ssp is based on controls included by the following: profile, components, implementation status, and/or control origination.

                                    Source code in trestle/core/commands/author/ssp.py
                                    class SSPFilter(AuthorCommonCommand):\n\"\"\"\n    Filter the controls in an ssp.\n\n    The filtered ssp is based on controls included by the following:\n    profile, components, implementation status, and/or control origination.\n    \"\"\"\n\n    name = 'ssp-filter'\n\n    def _init_arguments(self) -> None:\n        file_help_str = 'Name of the input ssp'\n        self.add_argument('-n', '--name', help=file_help_str, required=True, type=str)\n        file_help_str = 'Name of the optional input profile that defines set of controls in filtered ssp'\n        self.add_argument('-p', '--profile', help=file_help_str, required=False, type=str)\n        output_help_str = 'Name of the output generated SSP'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n        comp_help_str = 'Colon-delimited list of component names to include in filtered ssp.'\n        self.add_argument('-c', '--components', help=comp_help_str, required=False, type=str)\n        is_help_str = 'Comma-delimited list of control implementation statuses to include in filtered ssp.'\n        self.add_argument('-is', '--implementation-status', help=is_help_str, required=False, type=str)\n        co_help_str = 'Comma-delimited list of control origination values to include in filtered ssp.'\n        self.add_argument('-co', '--control-origination', help=co_help_str, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n            comp_names: Optional[List[str]] = None\n            impl_status_values: Optional[List[str]] = None\n            co_values: Optional[List[str]] = None\n\n            if not (args.components or args.implementation_status or args.profile or args.control_origination):\n                logger.warning(\n                    'You must specify at least one, or a combination of: profile, list of component names'\n                    ', list of implementation statuses, or list of control origination values for ssp-filter.'\n                )\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n            if args.components:\n                comp_names = args.components.split(':')\n\n            if args.implementation_status:\n                impl_status_values = args.implementation_status.split(',')\n                allowed_is_values = {\n                    const.STATUS_PLANNED,\n                    const.STATUS_PARTIAL,\n                    const.STATUS_IMPLEMENTED,\n                    const.STATUS_ALTERNATIVE,\n                    const.STATUS_NOT_APPLICABLE\n                }\n                allowed_is_string = ', '.join(str(item) for item in allowed_is_values)\n                for impl_status in impl_status_values:\n                    if impl_status not in allowed_is_values:\n                        logger.warning(\n                            f'Provided implementation status \"{impl_status}\" is invalid.\\n'\n                            f'Please use the following for ssp-filter: {allowed_is_string}'\n                        )\n                        return CmdReturnCodes.COMMAND_ERROR.value\n\n            if args.control_origination:\n                co_values = args.control_origination.split(',')\n                allowed_co_values = {\n                    const.ORIGINATION_ORGANIZATION,\n                    const.ORIGINATION_SYSTEM_SPECIFIC,\n                    const.ORIGINATION_INHERITED,\n                    const.ORIGINATION_CUSTOMER_CONFIGURED,\n                    const.ORIGINATION_CUSTOMER_PROVIDED\n                }\n                allowed_co_string = ', '.join(str(item) for item in allowed_co_values)\n                for co in co_values:\n                    if co not in allowed_co_values:\n                        logger.warning(\n                            f'Provided control origination \"{co}\" is invalid.\\n'\n                            f'Please use the following for ssp-filter: {allowed_co_string}'\n                        )\n                        return CmdReturnCodes.COMMAND_ERROR.value\n\n            return self.filter_ssp(\n                trestle_root,\n                args.name,\n                args.profile,\n                args.output,\n                args.regenerate,\n                args.version,\n                comp_names,\n                impl_status_values,\n                co_values\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error generating the filtered ssp')\n\n    def filter_ssp(\n        self,\n        trestle_root: pathlib.Path,\n        ssp_name: str,\n        profile_name: str,\n        out_name: str,\n        regenerate: bool,\n        version: Optional[str],\n        components: Optional[List[str]] = None,\n        implementation_status: Optional[List[str]] = None,\n        control_origination: Optional[List[str]] = None\n    ) -> int:\n\"\"\"\n        Filter the ssp and output new ssp.\n\n        The filtered ssp is based on controls included by the following:\n        profile, components, implementation status, and/or control origination.\n\n        Args:\n            trestle_root: root directory of the trestle workspace\n            ssp_name: name of the ssp model\n            profile_name: name of the optional profile model used for filtering\n            out_name: name of the output ssp model with filtered controls\n            regenerate: whether to regenerate the uuid's in the ssp\n            version: new version for the model\n            components: optional list of component names used for filtering\n            implementation_status: optional list of implementation statuses for filtering\n            control_origination: optional list of control origination values for filtering\n\n        Returns:\n            0 on success, 1 otherwise\n        \"\"\"\n        # load the ssp\n        ssp: ossp.SystemSecurityPlan\n        ssp, _ = load_validate_model_name(trestle_root, ssp_name, ossp.SystemSecurityPlan, FileContentType.JSON)\n        profile_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, profile_name, prof.Profile, FileContentType.JSON\n        )\n\n        if components:\n            raw_comp_names = [ControlReader.simplify_name(name) for name in components]\n            comp_uuids: List[str] = []\n            for component in ssp.system_implementation.components:\n                if ControlReader.simplify_name(component.title) in raw_comp_names:\n                    comp_uuids.append(component.uuid)\n\n            if len(comp_uuids) != len(components):\n                raise TrestleError(\n                    f'Unable to filter the ssp because one of the components {components} is not in the ssp.'\n                )\n\n            # imp_reqs can be by comp\n            # and imp_reqs can have statements that are by comp\n            if comp_uuids:\n                new_imp_reqs: List[ossp.ImplementedRequirement] = []\n                # these are all required to be present\n                for imp_req in ssp.control_implementation.implemented_requirements:\n                    new_by_comps: List[ossp.ByComponent] = []\n                    # by_comps is optional\n                    for by_comp in as_list(imp_req.by_components):\n                        if by_comp.component_uuid in comp_uuids:\n                            new_by_comps.append(by_comp)\n                    imp_req.by_components = none_if_empty(new_by_comps)\n                    new_imp_reqs.append(imp_req)\n                    new_statements: List[ossp.Statement] = []\n                    for statement in as_list(imp_req.statements):\n                        new_by_comps: List[ossp.ByComponent] = []\n                        for by_comp in as_list(statement.by_components):\n                            if by_comp.component_uuid in comp_uuids:\n                                new_by_comps.append(by_comp)\n                        statement.by_components = none_if_empty(new_by_comps)\n                        new_statements.append(statement)\n                    imp_req.statements = none_if_empty(new_statements)\n                ssp.control_implementation.implemented_requirements = new_imp_reqs\n                # now remove any unused components from the ssp\n                new_comp_list: List[ossp.SystemComponent] = []\n                for comp_ in ssp.system_implementation.components:\n                    if comp_.uuid in comp_uuids:\n                        new_comp_list.append(comp_)\n                ssp.system_implementation.components = new_comp_list\n\n        # filter by controls in profile\n        if profile_name:\n            prof_resolver = ProfileResolver()\n            catalog = prof_resolver.get_resolved_profile_catalog(trestle_root, profile_path, show_value_warnings=True)\n            catalog_api = CatalogAPI(catalog=catalog)\n\n            # The input ssp should reference a superset of the controls referenced by the profile\n            # Need to cull references in the ssp to controls not in the profile\n            # Also make sure the output ssp contains imp reqs for all controls in the profile\n            control_imp = ssp.control_implementation\n            ssp_control_ids: Set[str] = set()\n\n            new_set_params: List[ossp.SetParameter] = []\n            for set_param in as_list(control_imp.set_parameters):\n                control = catalog_api._catalog_interface.get_control_by_param_id(set_param.param_id)\n                if control is not None:\n                    new_set_params.append(set_param)\n                    ssp_control_ids.add(control.id)\n            control_imp.set_parameters = none_if_empty(new_set_params)\n\n            new_imp_requirements: List[ossp.ImplementedRequirement] = []\n            for imp_requirement in as_list(control_imp.implemented_requirements):\n                control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n                if control is not None:\n                    new_imp_requirements.append(imp_requirement)\n                    ssp_control_ids.add(control.id)\n            control_imp.implemented_requirements = new_imp_requirements\n\n            # make sure all controls in the profile have implemented reqs in the final ssp\n            if not ssp_control_ids.issuperset(catalog_api._catalog_interface.get_control_ids()):\n                raise TrestleError('Unable to filter the ssp because the profile references controls not in it.')\n\n            ssp.control_implementation = control_imp\n\n        # filter implemented requirements and statements by component implementation status\n        # this will remove any implemented requirements without statements or by_component fields set\n        if implementation_status:\n            new_imp_reqs: List[ossp.ImplementedRequirement] = []\n            # these are all required to be present\n            for imp_req in ssp.control_implementation.implemented_requirements:\n                new_by_comps: List[ossp.ByComponent] = []\n                # by_comps is optional\n                for by_comp in as_list(imp_req.by_components):\n                    if by_comp.implementation_status.state in implementation_status:\n                        new_by_comps.append(by_comp)\n                imp_req.by_components = none_if_empty(new_by_comps)\n\n                new_statements: List[ossp.Statement] = []\n                for statement in as_list(imp_req.statements):\n                    new_by_comps: List[ossp.ByComponent] = []\n                    for by_comp in as_list(statement.by_components):\n                        if by_comp.implementation_status.state in implementation_status:\n                            new_by_comps.append(by_comp)\n                    statement.by_components = none_if_empty(new_by_comps)\n                    if statement.by_components is not None:\n                        new_statements.append(statement)\n                imp_req.statements = none_if_empty(new_statements)\n\n                if imp_req.by_components is not None or imp_req.statements is not None:\n                    new_imp_reqs.append(imp_req)\n\n            ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n        # filter implemented requirements by control origination property.\n        # this will remove any implemented requirements without the control origination\n        # property set\n        if control_origination:\n            new_imp_reqs: List[ossp.ImplementedRequirement] = []\n\n            for imp_requirement in ssp.control_implementation.implemented_requirements:\n                if imp_requirement.props:\n                    for prop in imp_requirement.props:\n                        if prop.name == const.CONTROL_ORIGINATION and prop.value in control_origination:\n                            new_imp_reqs.append(imp_requirement)\n                            # only add the imp requirement one time\n                            break\n\n            ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n        if version:\n            ssp.metadata.version = version\n\n        existing_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, out_name, ossp.SystemSecurityPlan\n        )\n        if existing_ssp_path is not None:\n            existing_ssp, _ = load_validate_model_name(trestle_root, out_name, ossp.SystemSecurityPlan)\n            if ModelUtils.models_are_equivalent(existing_ssp, ssp):  # type: ignore\n                logger.info('No changes to filtered ssp so ssp not written out.')\n                return CmdReturnCodes.SUCCESS.value\n\n        if regenerate:\n            ssp, _, _ = ModelUtils.regenerate_uuids(ssp)\n\n        ModelUtils.update_last_modified(ssp)\n\n        ModelUtils.save_top_level_model(ssp, trestle_root, out_name, FileContentType.JSON)\n\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter.filter_ssp","title":"filter_ssp(self, trestle_root, ssp_name, profile_name, out_name, regenerate, version, components=None, implementation_status=None, control_origination=None)","text":"

                                    Filter the ssp and output new ssp.

                                    The filtered ssp is based on controls included by the following: profile, components, implementation status, and/or control origination.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    root directory of the trestle workspace

                                    required ssp_name str

                                    name of the ssp model

                                    required profile_name str

                                    name of the optional profile model used for filtering

                                    required out_name str

                                    name of the output ssp model with filtered controls

                                    required regenerate bool

                                    whether to regenerate the uuid's in the ssp

                                    required version Optional[str]

                                    new version for the model

                                    required components Optional[List[str]]

                                    optional list of component names used for filtering

                                    None implementation_status Optional[List[str]]

                                    optional list of implementation statuses for filtering

                                    None control_origination Optional[List[str]]

                                    optional list of control origination values for filtering

                                    None

                                    Returns:

                                    Type Description int

                                    0 on success, 1 otherwise

                                    Source code in trestle/core/commands/author/ssp.py
                                    def filter_ssp(\n    self,\n    trestle_root: pathlib.Path,\n    ssp_name: str,\n    profile_name: str,\n    out_name: str,\n    regenerate: bool,\n    version: Optional[str],\n    components: Optional[List[str]] = None,\n    implementation_status: Optional[List[str]] = None,\n    control_origination: Optional[List[str]] = None\n) -> int:\n\"\"\"\n    Filter the ssp and output new ssp.\n\n    The filtered ssp is based on controls included by the following:\n    profile, components, implementation status, and/or control origination.\n\n    Args:\n        trestle_root: root directory of the trestle workspace\n        ssp_name: name of the ssp model\n        profile_name: name of the optional profile model used for filtering\n        out_name: name of the output ssp model with filtered controls\n        regenerate: whether to regenerate the uuid's in the ssp\n        version: new version for the model\n        components: optional list of component names used for filtering\n        implementation_status: optional list of implementation statuses for filtering\n        control_origination: optional list of control origination values for filtering\n\n    Returns:\n        0 on success, 1 otherwise\n    \"\"\"\n    # load the ssp\n    ssp: ossp.SystemSecurityPlan\n    ssp, _ = load_validate_model_name(trestle_root, ssp_name, ossp.SystemSecurityPlan, FileContentType.JSON)\n    profile_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, profile_name, prof.Profile, FileContentType.JSON\n    )\n\n    if components:\n        raw_comp_names = [ControlReader.simplify_name(name) for name in components]\n        comp_uuids: List[str] = []\n        for component in ssp.system_implementation.components:\n            if ControlReader.simplify_name(component.title) in raw_comp_names:\n                comp_uuids.append(component.uuid)\n\n        if len(comp_uuids) != len(components):\n            raise TrestleError(\n                f'Unable to filter the ssp because one of the components {components} is not in the ssp.'\n            )\n\n        # imp_reqs can be by comp\n        # and imp_reqs can have statements that are by comp\n        if comp_uuids:\n            new_imp_reqs: List[ossp.ImplementedRequirement] = []\n            # these are all required to be present\n            for imp_req in ssp.control_implementation.implemented_requirements:\n                new_by_comps: List[ossp.ByComponent] = []\n                # by_comps is optional\n                for by_comp in as_list(imp_req.by_components):\n                    if by_comp.component_uuid in comp_uuids:\n                        new_by_comps.append(by_comp)\n                imp_req.by_components = none_if_empty(new_by_comps)\n                new_imp_reqs.append(imp_req)\n                new_statements: List[ossp.Statement] = []\n                for statement in as_list(imp_req.statements):\n                    new_by_comps: List[ossp.ByComponent] = []\n                    for by_comp in as_list(statement.by_components):\n                        if by_comp.component_uuid in comp_uuids:\n                            new_by_comps.append(by_comp)\n                    statement.by_components = none_if_empty(new_by_comps)\n                    new_statements.append(statement)\n                imp_req.statements = none_if_empty(new_statements)\n            ssp.control_implementation.implemented_requirements = new_imp_reqs\n            # now remove any unused components from the ssp\n            new_comp_list: List[ossp.SystemComponent] = []\n            for comp_ in ssp.system_implementation.components:\n                if comp_.uuid in comp_uuids:\n                    new_comp_list.append(comp_)\n            ssp.system_implementation.components = new_comp_list\n\n    # filter by controls in profile\n    if profile_name:\n        prof_resolver = ProfileResolver()\n        catalog = prof_resolver.get_resolved_profile_catalog(trestle_root, profile_path, show_value_warnings=True)\n        catalog_api = CatalogAPI(catalog=catalog)\n\n        # The input ssp should reference a superset of the controls referenced by the profile\n        # Need to cull references in the ssp to controls not in the profile\n        # Also make sure the output ssp contains imp reqs for all controls in the profile\n        control_imp = ssp.control_implementation\n        ssp_control_ids: Set[str] = set()\n\n        new_set_params: List[ossp.SetParameter] = []\n        for set_param in as_list(control_imp.set_parameters):\n            control = catalog_api._catalog_interface.get_control_by_param_id(set_param.param_id)\n            if control is not None:\n                new_set_params.append(set_param)\n                ssp_control_ids.add(control.id)\n        control_imp.set_parameters = none_if_empty(new_set_params)\n\n        new_imp_requirements: List[ossp.ImplementedRequirement] = []\n        for imp_requirement in as_list(control_imp.implemented_requirements):\n            control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n            if control is not None:\n                new_imp_requirements.append(imp_requirement)\n                ssp_control_ids.add(control.id)\n        control_imp.implemented_requirements = new_imp_requirements\n\n        # make sure all controls in the profile have implemented reqs in the final ssp\n        if not ssp_control_ids.issuperset(catalog_api._catalog_interface.get_control_ids()):\n            raise TrestleError('Unable to filter the ssp because the profile references controls not in it.')\n\n        ssp.control_implementation = control_imp\n\n    # filter implemented requirements and statements by component implementation status\n    # this will remove any implemented requirements without statements or by_component fields set\n    if implementation_status:\n        new_imp_reqs: List[ossp.ImplementedRequirement] = []\n        # these are all required to be present\n        for imp_req in ssp.control_implementation.implemented_requirements:\n            new_by_comps: List[ossp.ByComponent] = []\n            # by_comps is optional\n            for by_comp in as_list(imp_req.by_components):\n                if by_comp.implementation_status.state in implementation_status:\n                    new_by_comps.append(by_comp)\n            imp_req.by_components = none_if_empty(new_by_comps)\n\n            new_statements: List[ossp.Statement] = []\n            for statement in as_list(imp_req.statements):\n                new_by_comps: List[ossp.ByComponent] = []\n                for by_comp in as_list(statement.by_components):\n                    if by_comp.implementation_status.state in implementation_status:\n                        new_by_comps.append(by_comp)\n                statement.by_components = none_if_empty(new_by_comps)\n                if statement.by_components is not None:\n                    new_statements.append(statement)\n            imp_req.statements = none_if_empty(new_statements)\n\n            if imp_req.by_components is not None or imp_req.statements is not None:\n                new_imp_reqs.append(imp_req)\n\n        ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n    # filter implemented requirements by control origination property.\n    # this will remove any implemented requirements without the control origination\n    # property set\n    if control_origination:\n        new_imp_reqs: List[ossp.ImplementedRequirement] = []\n\n        for imp_requirement in ssp.control_implementation.implemented_requirements:\n            if imp_requirement.props:\n                for prop in imp_requirement.props:\n                    if prop.name == const.CONTROL_ORIGINATION and prop.value in control_origination:\n                        new_imp_reqs.append(imp_requirement)\n                        # only add the imp requirement one time\n                        break\n\n        ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n    if version:\n        ssp.metadata.version = version\n\n    existing_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, out_name, ossp.SystemSecurityPlan\n    )\n    if existing_ssp_path is not None:\n        existing_ssp, _ = load_validate_model_name(trestle_root, out_name, ossp.SystemSecurityPlan)\n        if ModelUtils.models_are_equivalent(existing_ssp, ssp):  # type: ignore\n            logger.info('No changes to filtered ssp so ssp not written out.')\n            return CmdReturnCodes.SUCCESS.value\n\n    if regenerate:\n        ssp, _, _ = ModelUtils.regenerate_uuids(ssp)\n\n    ModelUtils.update_last_modified(ssp)\n\n    ModelUtils.save_top_level_model(ssp, trestle_root, out_name, FileContentType.JSON)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPGenerate","title":" SSPGenerate (AuthorCommonCommand) ","text":"

                                    Generate SSP in markdown form from a Profile.

                                    Source code in trestle/core/commands/author/ssp.py
                                    class SSPGenerate(AuthorCommonCommand):\n\"\"\"Generate SSP in markdown form from a Profile.\"\"\"\n\n    name = 'ssp-generate'\n\n    def _init_arguments(self) -> None:\n        file_help_str = 'Main profile href, or name of the profile model in the trestle workspace'\n        self.add_argument('-p', '--profile', help=file_help_str, required=True, type=str)\n        self.add_argument(\n            '-o', '--output', help='Name of the output generated ssp markdown folder', required=True, type=str\n        )  # noqa E501\n        self.add_argument('-cd', '--compdefs', help=const.HELP_COMPDEFS, required=False, type=str)\n\n        ls_help_str = 'Leveraged ssp with inheritable controls href or name in the trestle_workspace'\n        self.add_argument('-ls', '--leveraged-ssp', help=ls_help_str, required=False, type=str)\n\n        self.add_argument('-y', '--yaml-header', help=const.HELP_YAML_PATH, required=False, type=str)\n        self.add_argument(\n            '-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true', default=False\n        )\n        self.add_argument(\n            '-ohv',\n            '--overwrite-header-values',\n            help=const.HELP_OVERWRITE_HEADER_VALUES,\n            required=False,\n            action='store_true',\n            default=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = args.trestle_root\n            if not file_utils.is_directory_name_allowed(args.output):\n                raise TrestleError(f'{args.output} is not an allowed directory name')\n\n            yaml_header: Dict[str, Any] = {}\n            if args.yaml_header:\n                try:\n                    logging.debug(f'Loading yaml header file {args.yaml_header}')\n                    yaml = YAML()\n                    yaml_header = yaml.load(pathlib.Path(args.yaml_header).open('r'))\n                except YAMLError as e:\n                    raise TrestleError(f'YAML error loading yaml header {args.yaml_header} for ssp generation: {e}')\n\n            compdef_name_list = comma_sep_to_list(args.compdefs)\n\n            md_path = trestle_root / args.output\n\n            return self._generate_ssp_markdown(\n                trestle_root,\n                args.profile,\n                compdef_name_list,\n                args.leveraged_ssp,\n                md_path,\n                yaml_header,\n                args.overwrite_header_values,\n                args.force_overwrite\n            )\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while writing markdown from catalog')\n\n    def _generate_ssp_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        profile_name_or_href: str,\n        compdef_name_list: List[str],\n        leveraged_ssp_name_or_href: str,\n        md_path: pathlib.Path,\n        yaml_header: Dict[str, Any],\n        overwrite_header_values: bool,\n        force_overwrite: bool\n    ) -> int:\n\"\"\"\n        Generate the ssp markdown from the profile and compdefs.\n\n        Notes:\n        Get RPC from profile.\n        For each compdef:\n            For each comp:\n                Load top level rules\n                for each control_imp:\n                    Load rules params values\n                    For each imp_req (bound to 1 control):\n                        Load control level rules and status\n                        Load part level rules\n                        If rules apply then write out control and add to list written out\n                        If control exists, read it and insert content\n        \"\"\"\n        if force_overwrite:\n            try:\n                logger.info(f'Overwriting the content in {md_path}.')\n                clear_folder(pathlib.Path(md_path))\n            except TrestleError as e:  # pragma: no cover\n                raise TrestleError(f'Unable to overwrite contents of {md_path}: {e}')\n\n        context = ControlContext.generate(ContextPurpose.SSP, True, trestle_root, md_path)\n        context.cli_yaml_header = yaml_header\n        context.sections_dict = None\n        context.prompt_responses = True\n        context.overwrite_header_values = overwrite_header_values\n        context.allowed_sections = None\n        context.comp_def_name_list = compdef_name_list\n\n        # if file not recognized as URI form, assume it represents name of file in trestle directory\n        profile_in_trestle_dir = '://' not in profile_name_or_href\n        profile_href = profile_name_or_href\n        if profile_in_trestle_dir:\n            local_path = f'profiles/{profile_name_or_href}/profile.json'\n            profile_href = const.TRESTLE_HREF_HEADING + local_path\n            profile_path = trestle_root / local_path\n            _, _, context.profile = ModelUtils.load_distributed(profile_path, trestle_root)\n        else:\n            fetcher = FetcherFactory.get_fetcher(trestle_root, profile_href)\n            context.profile = fetcher.get_oscal()\n            profile_path = profile_href\n\n        profile_resolver = ProfileResolver()\n        # in ssp context we want to see missing value warnings\n        resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            block_params=False,\n            params_format='[.]',\n            param_rep=ParameterRep.ASSIGNMENT_FORM,\n            show_value_warnings=True\n        )\n\n        catalog_api = CatalogAPI(catalog=resolved_catalog, context=context)\n\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG] = {}\n        profile_header = {'title': context.profile.metadata.title, 'href': profile_href}\n\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG][const.PROFILE] = profile_header\n\n        catalog_api.write_catalog_as_markdown()\n\n        # Generate inheritance view after controls view completes\n        if leveraged_ssp_name_or_href:\n            self._generate_inheritance_markdown(trestle_root, leveraged_ssp_name_or_href, resolved_catalog, md_path)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    def _generate_inheritance_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        leveraged_ssp_name_or_href: str,\n        resolved_catalog: CatalogInterface,\n        md_path: str\n    ) -> None:\n\"\"\"\n        Generate markdown for inheritance view.\n\n        Notes:\n            This will create the inheritance view markdown files in the same directory as the ssp markdown files.\n            The information will be from the leveraged ssp, but filtered by the chosen profile to ensure only relevant\n            controls are present for mapping.\n        \"\"\"\n        # if file not recognized as URI form, assume it represents name of file in trestle directory\n        ssp_in_trestle_dir = '://' not in leveraged_ssp_name_or_href\n        ssp_href = leveraged_ssp_name_or_href\n        if ssp_in_trestle_dir:\n            local_path = f'{const.MODEL_DIR_SSP}/{leveraged_ssp_name_or_href}/system-security-plan.json'\n            ssp_href = const.TRESTLE_HREF_HEADING + local_path\n\n        inheritance_view_path: pathlib.Path = md_path.joinpath(const.INHERITANCE_VIEW_DIR)\n        inheritance_view_path.mkdir(exist_ok=True)\n        logger.debug(f'Creating content for inheritance view in {inheritance_view_path}')\n\n        ssp_inheritance_api = SSPInheritanceAPI(inheritance_view_path, trestle_root)\n\n        # Filter the ssp implemented requirements by the catalog specified\n        catalog_api: CatalogAPI = CatalogAPI(catalog=resolved_catalog)\n        ssp_inheritance_api.write_inheritance_as_markdown(ssp_href, catalog_api)\n
                                    "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/","title":"template_versioning","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning","title":"trestle.core.commands.author.versioning.template_versioning","text":"

                                    A Template Versioning.

                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning","title":" TemplateVersioning ","text":"

                                    Template versioning solution.

                                    1. Load template with a specified version.
                                      1. Template version can be specified via -tv flag
                                      2. If no version specified the latest version will be used by default.
                                      3. Otherwise use the templates from the specified version.
                                    2. Backward compatibility.
                                      1. Version 0.0.1 will be reserved for the template versions prior to this change.
                                      2. If the old template path is detected (i.e. without the template version). then the filesystem will be updated to the new path with the version.
                                      3. Upon first run, old template versions prior to this change will be placed to the folder 0.0.1.
                                      4. If templates have no headers then 0.0.1 version will be used.
                                    3. Versioning organization.
                                      1. Template and instance version is added both: in the file system (via path) and in the headers or metadata.
                                    4. Instance version validation.
                                      1. Markdown:
                                        1. When validating the instance the header will be used to validate the version.
                                      2. Drawio:
                                        1. When validating the instance the metadata will be used to validate the version.
                                    Source code in trestle/core/commands/author/versioning/template_versioning.py
                                    class TemplateVersioning:\n\"\"\"\n    Template versioning solution.\n\n    1. Load template with a specified version.\n        1. Template version can be specified via -tv flag\n        2. If no version specified the latest version will be used by default.\n        3. Otherwise use the templates from the specified version.\n    2. Backward compatibility.\n        1. Version 0.0.1 will be reserved for the template versions prior to this change.\n        2. If the old template path is detected (i.e. without the template version).\n            then the filesystem will be updated to the new path with the version.\n        3. Upon first run, old template versions prior to this change will be placed to the folder 0.0.1.\n        4. If templates have no headers then 0.0.1 version will be used.\n    3. Versioning organization.\n        1. Template and instance version is added both: in the file system (via path) and in the headers or metadata.\n    4. Instance version validation.\n        1. Markdown:\n            1. When validating the instance the header will be used to validate the version.\n        2. Drawio:\n            1. When validating the instance the metadata will be used to validate the version.\n    \"\"\"\n\n    @staticmethod\n    def update_template_folder_structure(task_path: Path) -> None:\n\"\"\"\n        Automatically detect whether the path is an old style and update it.\n\n        An old-style path is a path of the form:\n         root_folder/.trestle/author/{template_name}/{template_objects}\n        The new version path is a path of the form:\n         root_folder/.trestle/author/{template_name}/{version}/{template_objects}\n        By default all old-style templates will be updated to version 0.0.1\n        \"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n\n        try:\n            all_files_wo_version = list(\n                filter(lambda p: p.is_file(), file_utils.iterdir_without_hidden_files(task_path))\n            )\n\n            pattern = re.compile(TEMPLATE_VERSION_REGEX)\n            all_non_template_directories = list(\n                filter(\n                    lambda p: p.is_dir() and pattern.search(p.parts[-1]) is None,\n                    file_utils.iterdir_without_hidden_files(task_path)\n                )\n            )\n\n            new_dir = Path(f'{task_path}/{START_TEMPLATE_VERSION}')\n            new_dir.mkdir(parents=True, exist_ok=True)\n\n            if len(all_files_wo_version) == 0:\n                logger.debug('No templates outside of the version folders.')\n                # if the base template folder is empty, delete it\n                if len(list(new_dir.iterdir())) == 0:\n                    new_dir.rmdir()\n\n            for f in all_files_wo_version + all_non_template_directories:\n                if f.is_file():\n                    shutil.copy(f, new_dir)\n                elif f.is_dir():\n                    shutil.copytree(f, new_dir / f.name)\n\n            for p in all_files_wo_version + all_non_template_directories:\n                if p.is_dir():\n                    shutil.rmtree(p)\n                else:\n                    p.unlink()\n\n        except OSError as e:\n            raise TrestleError(f'Error while updating template folder: {e}')\n        except Exception as e:\n            raise TrestleError(f'Unexpected error while updating template folder: {e}')\n\n    @staticmethod\n    def get_versioned_template_dir(task_path: Path, version: Optional[str] = None) -> Path:\n\"\"\"\n        Get a template folder of the specified version.\n\n        If no version is given, the latest version of template will be returned\n        \"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n        latest_path = None\n        if version is None:\n            latest_path, _ = TemplateVersioning.get_latest_version_for_task(task_path)\n        else:\n            latest_path = Path(f'{task_path}/{version}/')\n\n        if not latest_path.exists():\n            raise TrestleError(f'The task: {task_path} with version: {version} does not exists.')\n\n        return latest_path\n\n    @staticmethod\n    def get_latest_version_for_task(task_path: Path) -> Tuple[Path, str]:\n\"\"\"Get latest version of the template for the given task.\"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n\n        all_versions = TemplateVersioning.get_all_versions_for_task(task_path)\n        max_version = START_TEMPLATE_VERSION\n\n        if len(all_versions) == 0:\n            logger.debug(f'No template versions were found for task: {task_path}, defaulting to 0.0.1')\n            max_version = START_TEMPLATE_VERSION\n        else:\n            max_version = max(all_versions)\n\n        latest_path = Path(f'{task_path}/{max_version}')\n\n        return latest_path, max_version\n\n    @staticmethod\n    def get_all_versions_for_task(task_path: Path) -> List[str]:\n\"\"\"Get all versions for the task.\"\"\"\n        pattern = re.compile(TEMPLATE_VERSION_REGEX)\n        all_versions = []\n        max_version = START_TEMPLATE_VERSION\n        for p in task_path.iterdir():\n            if p.is_dir() and pattern.search(p.parts[-1]) is not None:\n                match = pattern.search(p.parts[-1]).string\n                all_versions.append(match)\n                if match > max_version:\n                    max_version = match\n\n        return all_versions\n\n    @staticmethod\n    def write_versioned_template(\n        resource_name: str, task_path: Path, target_file: Path, version: Optional[str] = None\n    ) -> None:\n\"\"\"\n        Write a template with the header or metadata of a specified version.\n\n        If no version was given the latest version for the task will be used.\n\n        Args:\n            resource_name:  Template resource name\n            task_path: Task path\n            target_file: File path where template will be written\n            version: return a resource of a specific version\n\n        Returns:\n            A dotted path of a versioned template, list of all available versions\n        \"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n        try:\n            templates_resource_path = TRESTLE_RESOURCES + '.templates'\n\n            ref = importlib_resources.files(templates_resource_path) / resource_name\n            with importlib_resources.as_file(ref) as generic_template:\n                if version is None:\n                    _, version = TemplateVersioning.get_latest_version_for_task(task_path)\n\n                # modify header/metadata in the template\n                if generic_template.suffix == MARKDOWN_FILE_EXT:\n                    md_api = MarkdownAPI()\n                    header, md_body = md_api.processor.read_markdown_wo_processing(generic_template)\n                    header[TEMPLATE_VERSION_HEADER] = version\n                    md_api.write_markdown_with_header(target_file, header, md_body)\n                    logger.debug(f'Successfully written template markdown to {target_file}')\n                elif generic_template.suffix == DRAWIO_FILE_EXT:\n                    drawio = DrawIO(generic_template)\n                    metadata = drawio.get_metadata()[0]\n                    metadata[TEMPLATE_VERSION_HEADER] = version\n\n                    drawio.write_drawio_with_metadata(generic_template, metadata, 0, target_file)\n                    logger.debug(f'Successfully written template drawio to {target_file}')\n                else:\n                    raise TrestleError(f'Unsupported template file extension {generic_template.suffix}')\n        except OSError as e:\n            raise TrestleError(f'Error while updating template folder: {e}')\n\n    @staticmethod\n    def is_valid_version(template_version: str) -> bool:\n\"\"\"Check if the version format is correct.\"\"\"\n        if template_version is None:\n            return True  # we can have empty version\n        if template_version == '0.0.0':\n            return False\n        version_regex = r'^[0-9]+\\.[0-9]+\\.[0-9]+$'\n        pattern = re.compile(version_regex)\n        if pattern.search(template_version):\n            return True\n        else:\n            return False\n\n    @staticmethod\n    def _check_if_exists_and_dir(task_path: Path) -> None:\n        if not task_path.exists():\n            raise TrestleError(f'Path: {task_path} does not exists.')\n\n        if not task_path.is_dir():\n            raise TrestleError(f'File {task_path} passed, however template directory is expected.')\n
                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.get_all_versions_for_task","title":"get_all_versions_for_task(task_path) staticmethod","text":"

                                    Get all versions for the task.

                                    Source code in trestle/core/commands/author/versioning/template_versioning.py
                                    @staticmethod\ndef get_all_versions_for_task(task_path: Path) -> List[str]:\n\"\"\"Get all versions for the task.\"\"\"\n    pattern = re.compile(TEMPLATE_VERSION_REGEX)\n    all_versions = []\n    max_version = START_TEMPLATE_VERSION\n    for p in task_path.iterdir():\n        if p.is_dir() and pattern.search(p.parts[-1]) is not None:\n            match = pattern.search(p.parts[-1]).string\n            all_versions.append(match)\n            if match > max_version:\n                max_version = match\n\n    return all_versions\n
                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.get_latest_version_for_task","title":"get_latest_version_for_task(task_path) staticmethod","text":"

                                    Get latest version of the template for the given task.

                                    Source code in trestle/core/commands/author/versioning/template_versioning.py
                                    @staticmethod\ndef get_latest_version_for_task(task_path: Path) -> Tuple[Path, str]:\n\"\"\"Get latest version of the template for the given task.\"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n\n    all_versions = TemplateVersioning.get_all_versions_for_task(task_path)\n    max_version = START_TEMPLATE_VERSION\n\n    if len(all_versions) == 0:\n        logger.debug(f'No template versions were found for task: {task_path}, defaulting to 0.0.1')\n        max_version = START_TEMPLATE_VERSION\n    else:\n        max_version = max(all_versions)\n\n    latest_path = Path(f'{task_path}/{max_version}')\n\n    return latest_path, max_version\n
                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.get_versioned_template_dir","title":"get_versioned_template_dir(task_path, version=None) staticmethod","text":"

                                    Get a template folder of the specified version.

                                    If no version is given, the latest version of template will be returned

                                    Source code in trestle/core/commands/author/versioning/template_versioning.py
                                    @staticmethod\ndef get_versioned_template_dir(task_path: Path, version: Optional[str] = None) -> Path:\n\"\"\"\n    Get a template folder of the specified version.\n\n    If no version is given, the latest version of template will be returned\n    \"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n    latest_path = None\n    if version is None:\n        latest_path, _ = TemplateVersioning.get_latest_version_for_task(task_path)\n    else:\n        latest_path = Path(f'{task_path}/{version}/')\n\n    if not latest_path.exists():\n        raise TrestleError(f'The task: {task_path} with version: {version} does not exists.')\n\n    return latest_path\n
                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.is_valid_version","title":"is_valid_version(template_version) staticmethod","text":"

                                    Check if the version format is correct.

                                    Source code in trestle/core/commands/author/versioning/template_versioning.py
                                    @staticmethod\ndef is_valid_version(template_version: str) -> bool:\n\"\"\"Check if the version format is correct.\"\"\"\n    if template_version is None:\n        return True  # we can have empty version\n    if template_version == '0.0.0':\n        return False\n    version_regex = r'^[0-9]+\\.[0-9]+\\.[0-9]+$'\n    pattern = re.compile(version_regex)\n    if pattern.search(template_version):\n        return True\n    else:\n        return False\n
                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.update_template_folder_structure","title":"update_template_folder_structure(task_path) staticmethod","text":"

                                    Automatically detect whether the path is an old style and update it.

                                    An old-style path is a path of the form: root_folder/.trestle/author/{template_name}/{template_objects} The new version path is a path of the form: root_folder/.trestle/author/{template_name}/{version}/{template_objects} By default all old-style templates will be updated to version 0.0.1

                                    Source code in trestle/core/commands/author/versioning/template_versioning.py
                                    @staticmethod\ndef update_template_folder_structure(task_path: Path) -> None:\n\"\"\"\n    Automatically detect whether the path is an old style and update it.\n\n    An old-style path is a path of the form:\n     root_folder/.trestle/author/{template_name}/{template_objects}\n    The new version path is a path of the form:\n     root_folder/.trestle/author/{template_name}/{version}/{template_objects}\n    By default all old-style templates will be updated to version 0.0.1\n    \"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n\n    try:\n        all_files_wo_version = list(\n            filter(lambda p: p.is_file(), file_utils.iterdir_without_hidden_files(task_path))\n        )\n\n        pattern = re.compile(TEMPLATE_VERSION_REGEX)\n        all_non_template_directories = list(\n            filter(\n                lambda p: p.is_dir() and pattern.search(p.parts[-1]) is None,\n                file_utils.iterdir_without_hidden_files(task_path)\n            )\n        )\n\n        new_dir = Path(f'{task_path}/{START_TEMPLATE_VERSION}')\n        new_dir.mkdir(parents=True, exist_ok=True)\n\n        if len(all_files_wo_version) == 0:\n            logger.debug('No templates outside of the version folders.')\n            # if the base template folder is empty, delete it\n            if len(list(new_dir.iterdir())) == 0:\n                new_dir.rmdir()\n\n        for f in all_files_wo_version + all_non_template_directories:\n            if f.is_file():\n                shutil.copy(f, new_dir)\n            elif f.is_dir():\n                shutil.copytree(f, new_dir / f.name)\n\n        for p in all_files_wo_version + all_non_template_directories:\n            if p.is_dir():\n                shutil.rmtree(p)\n            else:\n                p.unlink()\n\n    except OSError as e:\n        raise TrestleError(f'Error while updating template folder: {e}')\n    except Exception as e:\n        raise TrestleError(f'Unexpected error while updating template folder: {e}')\n
                                    "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.write_versioned_template","title":"write_versioned_template(resource_name, task_path, target_file, version=None) staticmethod","text":"

                                    Write a template with the header or metadata of a specified version.

                                    If no version was given the latest version for the task will be used.

                                    Parameters:

                                    Name Type Description Default resource_name str

                                    Template resource name

                                    required task_path Path

                                    Task path

                                    required target_file Path

                                    File path where template will be written

                                    required version Optional[str]

                                    return a resource of a specific version

                                    None

                                    Returns:

                                    Type Description None

                                    A dotted path of a versioned template, list of all available versions

                                    Source code in trestle/core/commands/author/versioning/template_versioning.py
                                    @staticmethod\ndef write_versioned_template(\n    resource_name: str, task_path: Path, target_file: Path, version: Optional[str] = None\n) -> None:\n\"\"\"\n    Write a template with the header or metadata of a specified version.\n\n    If no version was given the latest version for the task will be used.\n\n    Args:\n        resource_name:  Template resource name\n        task_path: Task path\n        target_file: File path where template will be written\n        version: return a resource of a specific version\n\n    Returns:\n        A dotted path of a versioned template, list of all available versions\n    \"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n    try:\n        templates_resource_path = TRESTLE_RESOURCES + '.templates'\n\n        ref = importlib_resources.files(templates_resource_path) / resource_name\n        with importlib_resources.as_file(ref) as generic_template:\n            if version is None:\n                _, version = TemplateVersioning.get_latest_version_for_task(task_path)\n\n            # modify header/metadata in the template\n            if generic_template.suffix == MARKDOWN_FILE_EXT:\n                md_api = MarkdownAPI()\n                header, md_body = md_api.processor.read_markdown_wo_processing(generic_template)\n                header[TEMPLATE_VERSION_HEADER] = version\n                md_api.write_markdown_with_header(target_file, header, md_body)\n                logger.debug(f'Successfully written template markdown to {target_file}')\n            elif generic_template.suffix == DRAWIO_FILE_EXT:\n                drawio = DrawIO(generic_template)\n                metadata = drawio.get_metadata()[0]\n                metadata[TEMPLATE_VERSION_HEADER] = version\n\n                drawio.write_drawio_with_metadata(generic_template, metadata, 0, target_file)\n                logger.debug(f'Successfully written template drawio to {target_file}')\n            else:\n                raise TrestleError(f'Unsupported template file extension {generic_template.suffix}')\n    except OSError as e:\n        raise TrestleError(f'Error while updating template folder: {e}')\n
                                    "},{"location":"api_reference/trestle.core.commands.command_docs/","title":"command_docs","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs","title":"trestle.core.commands.command_docs","text":"

                                    Trestle command abstraction.

                                    Improves parsing until such a point as ILCLI is fixed.

                                    "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandBase","title":" CommandBase (Command) ","text":"

                                    Linear extension to the ILCLI interface to use documentation string more.

                                    Trestle commands not requiring trestle-root should extend from this class.

                                    Source code in trestle/core/commands/command_docs.py
                                    class CommandBase(Command):\n\"\"\"Linear extension to the ILCLI interface to use documentation string more.\n\n    Trestle commands not requiring trestle-root should extend from this class.\n    \"\"\"\n\n    # Example commands extedning from this class - init', 'trestle', 'version', 'partial-object-validate'\n    def __init__(\n        self,\n        parser: Optional[argparse.ArgumentParser] = None,\n        parent: Optional[Command] = None,\n        name: Optional[str] = None,\n        out: Optional[TextIO] = None,\n        err: Optional[TextIO] = None\n    ) -> None:\n\"\"\"Override default ILCLI behaviour to include class documentation in command help description.\"\"\"\n        super(CommandBase, self).__init__(parser, parent, name, out, err)\n        self.parser.description = self.__doc__\n
                                    "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandBase.__init__","title":"__init__(self, parser=None, parent=None, name=None, out=None, err=None) special","text":"

                                    Override default ILCLI behaviour to include class documentation in command help description.

                                    Source code in trestle/core/commands/command_docs.py
                                    def __init__(\n    self,\n    parser: Optional[argparse.ArgumentParser] = None,\n    parent: Optional[Command] = None,\n    name: Optional[str] = None,\n    out: Optional[TextIO] = None,\n    err: Optional[TextIO] = None\n) -> None:\n\"\"\"Override default ILCLI behaviour to include class documentation in command help description.\"\"\"\n    super(CommandBase, self).__init__(parser, parent, name, out, err)\n    self.parser.description = self.__doc__\n
                                    "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandPlusDocs","title":" CommandPlusDocs (CommandBase) ","text":"

                                    This class validates trestle-root argument.

                                    Trestle commands requiring trestle-root should extend from this class. All commands that extend this class will validate the state of trestle workspace.

                                    Source code in trestle/core/commands/command_docs.py
                                    class CommandPlusDocs(CommandBase):\n\"\"\"This class validates trestle-root argument.\n\n    Trestle commands requiring trestle-root should extend from this class.\n    All commands that extend this class will validate the state of trestle workspace.\n    \"\"\"\n\n    def _validate_arguments(self, args: argparse.ArgumentParser) -> int:\n\"\"\"Check trestle-root argument is a valid trestle root directory.\"\"\"\n        root = file_utils.extract_trestle_project_root(args.trestle_root)  # type: ignore\n        if root is None:\n            logger.error(f'Given directory {args.trestle_root} is not in a valid trestle root directory')\n            return CmdReturnCodes.TRESTLE_ROOT_ERROR.value\n        is_oscal_dir_valid = file_utils.check_oscal_directories(args.trestle_root)  # type: ignore\n        if not is_oscal_dir_valid:\n            return CmdReturnCodes.TRESTLE_ROOT_ERROR.value\n        args.trestle_root = root  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/","title":"cmd_utils","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils","title":"trestle.core.commands.common.cmd_utils","text":"

                                    Trestle command related utilities.

                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.clear_folder","title":"clear_folder(folder_path)","text":"

                                    Clear all contents of the specified folder.

                                    Source code in trestle/core/commands/common/cmd_utils.py
                                    def clear_folder(folder_path: pathlib.Path) -> None:\n\"\"\"Clear all contents of the specified folder.\"\"\"\n    if not folder_path.exists() or not folder_path.is_dir():\n        return\n    try:\n        shutil.rmtree(folder_path)\n    except OSError as e:  # pragma: no cover\n        raise TrestleError(f'Error deleting contents of {folder_path}: {e}')\n
                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.model_type_is_too_granular","title":"model_type_is_too_granular(model_type)","text":"

                                    Is an model_type too fine to split.

                                    Source code in trestle/core/commands/common/cmd_utils.py
                                    def model_type_is_too_granular(model_type: Type[Any]) -> bool:\n\"\"\"Is an model_type too fine to split.\"\"\"\n    if type_utils.is_collection_field_type(model_type):\n        return False\n    if hasattr(model_type, '__fields__') and '__root__' in model_type.__fields__:\n        return True\n    if model_type.__name__ in ['str', 'ConstrainedStrValue', 'int', 'float', 'datetime']:\n        return True\n    return False\n
                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.parse_chain","title":"parse_chain(model_obj, path_parts, relative_path=None)","text":"

                                    Parse the model chain starting from the beginning.

                                    Parameters:

                                    Name Type Description Default model_obj Optional[trestle.core.base_model.OscalBaseModel]

                                    Model to use for inspecting available elements, if available or none

                                    required path_parts List[str]

                                    list of string paths to parse including wildcards

                                    required relative_path Optional[pathlib.Path]

                                    Optional relative path (w.r.t trestle workspace root directory)

                                    None

                                    Returns:

                                    Type Description List[trestle.core.models.elements.ElementPath]

                                    List of ElementPath

                                    Source code in trestle/core/commands/common/cmd_utils.py
                                    def parse_chain(\n    model_obj: Union[OscalBaseModel, None],\n    path_parts: List[str],\n    relative_path: Optional[pathlib.Path] = None\n) -> List[ElementPath]:\n\"\"\"Parse the model chain starting from the beginning.\n\n    Args:\n        model_obj: Model to use for inspecting available elements, if available or none\n        path_parts: list of string paths to parse including wildcards\n        relative_path: Optional relative path (w.r.t trestle workspace root directory)\n\n    Returns:\n        List of ElementPath\n    \"\"\"\n    element_paths: List[ElementPath] = []\n    sub_model = model_obj\n    have_model_to_parse = model_obj is not None\n\n    prev_element_path = None\n    latest_path = None\n    parent_model = path_parts[0]\n    i = 1\n    while i < len(path_parts):\n        p = path_parts[i]\n\n        # if hit wildcard create element path up to this point\n        if p == ElementPath.WILDCARD and len(element_paths) > 0:\n            # append wildcard to the latest element path\n            latest_path = element_paths.pop()\n            if latest_path.get_last() == ElementPath.WILDCARD:\n                raise TrestleError(f'Invalid element path with consecutive {ElementPath.WILDCARD}')\n\n            latest_path_str = ElementPath.PATH_SEPARATOR.join([latest_path.to_string(), p])\n            element_path = ElementPath(latest_path_str, latest_path.get_parent())\n        else:\n            # create and append element_path\n            # at this point sub_model may be a list of items\n            # new element path is needed only if any of the items contains the desired part\n            if p != ElementPath.WILDCARD:\n                new_attrib = str_utils.dash_to_underscore(p)\n                if isinstance(sub_model, list):\n                    for item in sub_model:\n                        # go into the list and find one with requested part\n                        sub_item = getattr(item, new_attrib, None)\n                        if sub_item is not None:\n                            sub_model = sub_item\n                            break\n                else:\n                    sub_model = getattr(sub_model, new_attrib, None)\n            if have_model_to_parse and sub_model is None:\n                return element_paths\n            p = ElementPath.PATH_SEPARATOR.join([parent_model, p])\n            element_path = ElementPath(p, parent_path=prev_element_path)\n\n        # If the path has wildcard and there are more parts later,\n        # get the parent model for the alias path\n        # If path has wildcard and it does not refer to a list, then there can be nothing after *\n        if element_path.get_last() == ElementPath.WILDCARD:\n            full_path_str = ElementPath.PATH_SEPARATOR.join(element_path.get_full_path_parts()[:-1])\n            parent_model = ModelUtils.get_singular_alias(full_path_str, relative_path)\n            # Does wildcard mean we need to inspect the sub_model to determine what can be split off from it?\n            # If it has __root__ it may mean it contains a list of objects and should be split as a list\n            if isinstance(sub_model, OscalBaseModel):\n                root = getattr(sub_model, '__root__', None)\n                if root is None or not isinstance(root, list):\n                    # Cannot have parts beyond * if it isn't a list\n                    if i < len(path_parts) - 1:\n                        raise TrestleError(\n                            f'Cannot split beyond * when the wildcard does not refer to a list.  Path: {path_parts}'\n                        )\n                    for key in sub_model.__fields__.keys():\n                        # only create element path is item is present in the sub_model\n                        if getattr(sub_model, key, None) is None:\n                            continue\n                        new_alias = str_utils.underscore_to_dash(key)\n                        new_path = full_path_str + '.' + new_alias\n                        if not split_is_too_fine(new_path, model_obj):\n                            # to add parts of an element, need to add two links\n                            # prev_element_path may be None, for example catalog.*\n                            if prev_element_path is not None:\n                                element_paths.append(prev_element_path)\n                            element_paths.append(ElementPath(parent_model + '.' + new_alias, latest_path))\n                    # Since wildcard is last in the chain when splitting an oscal model we are done\n                    return element_paths\n        else:\n            parent_model = element_path.get_element_name()\n\n        # store values for next cycle\n        prev_element_path = element_path\n        element_paths.append(element_path)\n        i += 1\n    return element_paths\n
                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.parse_element_arg","title":"parse_element_arg(model_obj, element_arg, relative_path=None)","text":"

                                    Parse an element arg string into a list of ElementPath.

                                    Parameters:

                                    Name Type Description Default model_obj Optional[trestle.core.base_model.OscalBaseModel]

                                    The OscalBaseModel being inspected to determine available elements that can be split

                                    required element_arg str

                                    Single element path, as a string.

                                    required relative_path Optional[pathlib.Path]

                                    Optional relative path (from trestle root) used to validate element args are valid.

                                    None

                                    Returns:

                                    Type Description List[trestle.core.models.elements.ElementPath]

                                    The requested parsed list of ElementPath for use in split

                                    Source code in trestle/core/commands/common/cmd_utils.py
                                    def parse_element_arg(\n    model_obj: Union[OscalBaseModel, None],\n    element_arg: str,\n    relative_path: Optional[pathlib.Path] = None\n) -> List[ElementPath]:\n\"\"\"Parse an element arg string into a list of ElementPath.\n\n    Args:\n        model_obj: The OscalBaseModel being inspected to determine available elements that can be split\n        element_arg: Single element path, as a string.\n        relative_path: Optional relative path (from trestle root) used to validate element args are valid.\n    Returns:\n        The requested parsed list of ElementPath for use in split\n    \"\"\"\n    element_arg = element_arg.strip()\n\n    if element_arg == '*':\n        raise TrestleError('Invalid element path containing only a single wildcard.')\n\n    if element_arg == '':\n        raise TrestleError('Invalid element path is empty string.')\n\n    # search for wildcards and create paths with its parent path\n    path_parts = element_arg.split(ElementPath.PATH_SEPARATOR)\n    if len(path_parts) <= 1:\n        raise TrestleError(f'Invalid element path \"{element_arg}\" with only one element and no wildcard')\n\n    element_paths = parse_chain(model_obj, path_parts, relative_path)\n\n    if len(element_paths) <= 0:\n        # don't complain if nothing to split\n        pass\n\n    return element_paths\n
                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.parse_element_args","title":"parse_element_args(model, element_args, relative_path=None)","text":"

                                    Parse element args into a list of ElementPath.

                                    The element paths are either simple links of two elements, or two elements followed by *. The * represents either a list of the items in that element, or a splitting of that element into its parts. The only parts split off are the non-trivial ones determined by the granularity check.

                                    contextual_mode specifies if the path is a valid project model path or not. For example, if we are processing a metadata.parties.*, we need to know which metadata we are processing. If we pass contextual_mode=true, we can infer the root model by inspecting the file directory

                                    If contextual_mode=False, then the path must include the full path, e.g. catalog.metadata.parties. instead of just metadata.parties.

                                    When the * represents splitting a model rather than a list, the model is inspected for what parts are available, and for each new part two element paths are created, one for the parent to the current element, and another from the current element to the child.

                                    A path may have multiple *'s, but only the final one can represent splitting a model.

                                    Parameters:

                                    Name Type Description Default model Optional[trestle.core.base_model.OscalBaseModel]

                                    The OscalBaseModel being inspected to determine available elements that can be split

                                    required element_args List[str]

                                    List of str representing links in the chain of element paths to be parsed

                                    required relative_path Optional[pathlib.Path]

                                    Optional relative path (from trestle root) used to validate element args are valid.

                                    None

                                    Returns:

                                    Type Description List[trestle.core.models.elements.ElementPath]

                                    The requested parsed list of ElementPath for use in split

                                    Source code in trestle/core/commands/common/cmd_utils.py
                                    def parse_element_args(\n    model: Union[OscalBaseModel, None],\n    element_args: List[str],\n    relative_path: Optional[pathlib.Path] = None\n) -> List[ElementPath]:\n\"\"\"Parse element args into a list of ElementPath.\n\n    The element paths are either simple links of two elements, or two elements followed by *.\n    The * represents either a list of the items in that element, or a splitting of that element into its parts.\n    The only parts split off are the non-trivial ones determined by the granularity check.\n\n    contextual_mode specifies if the path is a valid project model path or not. For example,\n    if we are processing a metadata.parties.*, we need to know which metadata we are processing. If we pass\n    contextual_mode=true, we can infer the root model by inspecting the file directory\n\n    If contextual_mode=False, then the path must include the full path, e.g. catalog.metadata.parties.* instead of just\n    metadata.parties.*\n\n    When the * represents splitting a model rather than a list, the model is inspected for what parts are available,\n    and for each new part two element paths are created, one for the parent to the current element, and another from\n    the current element to the child.\n\n    A path may have multiple *'s, but only the final one can represent splitting a model.\n\n    Args:\n        model: The OscalBaseModel being inspected to determine available elements that can be split\n        element_args: List of str representing links in the chain of element paths to be parsed\n        relative_path: Optional relative path (from trestle root) used to validate element args are valid.\n    Returns:\n        The requested parsed list of ElementPath for use in split\n    \"\"\"\n    # collect all paths\n    element_paths: List[ElementPath] = []\n    for element_arg in element_args:\n        paths = parse_element_arg(model, element_arg, relative_path)\n        element_paths.extend(paths)\n\n    return element_paths\n
                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.split_is_too_fine","title":"split_is_too_fine(split_paths, model_obj)","text":"

                                    Determine if the element path list goes too fine, e.g. individual strings.

                                    Source code in trestle/core/commands/common/cmd_utils.py
                                    def split_is_too_fine(split_paths: str, model_obj: OscalBaseModel) -> bool:\n\"\"\"Determine if the element path list goes too fine, e.g. individual strings.\"\"\"\n    for split_path in split_paths.split(','):\n        # find model type one level above if finishing with '.*'\n        model_type = ElementPath(split_path.rstrip('.*')).get_type(type(model_obj))\n        if model_type_is_too_granular(model_type):\n            return True\n    return False\n
                                    "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.to_model_file_name","title":"to_model_file_name(model_obj, file_prefix, content_type)","text":"

                                    Return the file name for the item.

                                    Source code in trestle/core/commands/common/cmd_utils.py
                                    def to_model_file_name(model_obj: OscalBaseModel, file_prefix: str, content_type: FileContentType) -> str:\n\"\"\"Return the file name for the item.\"\"\"\n    file_ext = FileContentType.to_file_extension(content_type)\n    model_type = classname_to_alias(type(model_obj).__name__, AliasMode.JSON)\n    file_name = f'{file_prefix}{const.IDX_SEP}{model_type}{file_ext}'\n    return file_name\n
                                    "},{"location":"api_reference/trestle.core.commands.common.return_codes/","title":"return_codes","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes","title":"trestle.core.commands.common.return_codes","text":"

                                    Trestle command return codes.

                                    "},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes","title":" CmdReturnCodes (Enum) ","text":"

                                    Trestle CLI return codes.

                                    SUCCESS - Operation/validation completed successfully COMMAND_ERROR - Generic expected error while executing command (handled by command) INCORRECT_ARGS - Provided arguments were incorrect/incomplete DOCUMENTS_VALIDATION_ERROR - Validation of the markdown or drawio files failed MODEL_VALIDATION_ERROR - Validation of OSCAL model failed TRESTLE_ROOT_ERROR - Workspace setup has failed, the root is not trestle directory IO_ERROR - IO related errors, i.e. permission issue, non-existing file, etc AUTH_ERROR - Authenication error while accessing/storing cache UNKNOWN_ERROR - Unexpected error (unhandled by command) INVALID_MODEL - Loaded model is invalid

                                    Source code in trestle/core/commands/common/return_codes.py
                                    class CmdReturnCodes(enum.Enum):\n\"\"\"\n    Trestle CLI return codes.\n\n    SUCCESS - Operation/validation completed successfully\n    COMMAND_ERROR - Generic expected error while executing command (handled by command)\n    INCORRECT_ARGS - Provided arguments were incorrect/incomplete\n    DOCUMENTS_VALIDATION_ERROR - Validation of the markdown or drawio files failed\n    MODEL_VALIDATION_ERROR - Validation of OSCAL model failed\n    TRESTLE_ROOT_ERROR - Workspace setup has failed, the root is not trestle directory\n    IO_ERROR - IO related errors, i.e. permission issue, non-existing file, etc\n    AUTH_ERROR - Authenication error while accessing/storing cache\n    UNKNOWN_ERROR - Unexpected error (unhandled by command)\n    INVALID_MODEL - Loaded model is invalid\n    \"\"\"\n\n    SUCCESS = 0\n    COMMAND_ERROR = 1\n    INCORRECT_ARGS = 2\n    DOCUMENTS_VALIDATION_ERROR = 3\n    OSCAL_VALIDATION_ERROR = 4\n    TRESTLE_ROOT_ERROR = 5\n    IO_ERROR = 6\n    AUTH_ERROR = 7\n    UNKNOWN_ERROR = 8\n
                                    "},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.AUTH_ERROR","title":"AUTH_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.COMMAND_ERROR","title":"COMMAND_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.DOCUMENTS_VALIDATION_ERROR","title":"DOCUMENTS_VALIDATION_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.INCORRECT_ARGS","title":"INCORRECT_ARGS","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.IO_ERROR","title":"IO_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.OSCAL_VALIDATION_ERROR","title":"OSCAL_VALIDATION_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.SUCCESS","title":"SUCCESS","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.TRESTLE_ROOT_ERROR","title":"TRESTLE_ROOT_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.UNKNOWN_ERROR","title":"UNKNOWN_ERROR","text":""},{"location":"api_reference/trestle.core.commands.create/","title":"create","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create","title":"trestle.core.commands.create","text":"

                                    Trestle Create CommandPlusDocs.

                                    "},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd","title":" CreateCmd (CommandPlusDocs) ","text":"

                                    Create a sample OSCAL model in trestle workspace or create new elements within a given model.

                                    Source code in trestle/core/commands/create.py
                                    class CreateCmd(CommandPlusDocs):\n\"\"\"Create a sample OSCAL model in trestle workspace or create new elements within a given model.\"\"\"\n\n    name = 'create'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-t', '--type', help='Type of model if created anew.', choices=const.MODEL_TYPE_LIST)\n        self.add_argument('-o', '--output', help='Name of the output created model.')\n        self.add_argument(const.IOF_SHORT, const.IOF_LONG, help=const.IOF_HELP, action='store_true')\n        self.add_argument(\n            '-x', '--extension', help='Type of file output.', choices=['json', 'yaml', 'yml'], default='json'\n        )\n        self.add_argument(\n            '-f', '--file', help='Optional existing OSCAL file that will have elements created within it.', type=str\n        )\n        self.add_argument(\n            '-e', '--element', help='Optional path of element to be created whithin the specified file.', type=str\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"\n        Execute the create command.\n\n        Notes\n            Either a new model will be created of the specified type,\n            or an existing file will have new elements added within it.\n        \"\"\"\n        try:\n            # Normal create path\n            if args.type and args.output:\n                object_type = ElementPath(args.type).get_type()\n                return self.create_object(args.type, object_type, args)\n            # Add path\n            elif args.file and args.element:\n                add = Add()\n                return add.add_from_args(args)\n\n            raise err.TrestleIncorrectArgsError(\n                'Create requires either a model type and output name, or a file and element path.'\n            )\n\n        except Exception as e:  # pragma: no cover\n            return err.handle_generic_command_exception(e, logger, 'Error while creating a sample OSCAL model')\n\n    @classmethod\n    def create_object(cls, model_alias: str, object_type: Type[TopLevelOscalModel], args: argparse.Namespace) -> int:\n\"\"\"Create a top level OSCAL object within the trestle directory, leveraging functionality in add.\"\"\"\n        log.set_log_level_from_args(args)\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n        if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n            raise err.TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n        desired_model_dir = trestle_root / plural_path / args.output\n\n        desired_model_path = desired_model_dir / (model_alias + '.' + args.extension)\n\n        if desired_model_path.exists():\n            raise err.TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n        # Create sample model.\n        sample_model = generators.generate_sample_model(object_type, include_optional=args.include_optional_fields)\n        # Presuming top level level model not sure how to do the typing for this.\n        sample_model.metadata.title = f'Generic {model_alias} created by trestle named {args.output}.'\n        sample_model.metadata.last_modified = datetime.now().astimezone()\n        sample_model.metadata.oscal_version = trestle.oscal.OSCAL_VERSION\n        sample_model.metadata.version = '0.0.0'\n\n        top_element = Element(sample_model, model_alias)\n\n        create_action = CreatePathAction(desired_model_path.resolve(), True)\n        write_action = WriteFileAction(\n            desired_model_path.resolve(), top_element, FileContentType.to_content_type(desired_model_path.suffix)\n        )\n\n        # create a plan to write the directory and file.\n        create_plan = Plan()\n        create_plan.add_action(create_action)\n        create_plan.add_action(write_action)\n        create_plan.execute()\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd.create_object","title":"create_object(model_alias, object_type, args) classmethod","text":"

                                    Create a top level OSCAL object within the trestle directory, leveraging functionality in add.

                                    Source code in trestle/core/commands/create.py
                                    @classmethod\ndef create_object(cls, model_alias: str, object_type: Type[TopLevelOscalModel], args: argparse.Namespace) -> int:\n\"\"\"Create a top level OSCAL object within the trestle directory, leveraging functionality in add.\"\"\"\n    log.set_log_level_from_args(args)\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n    if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n        raise err.TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n    desired_model_dir = trestle_root / plural_path / args.output\n\n    desired_model_path = desired_model_dir / (model_alias + '.' + args.extension)\n\n    if desired_model_path.exists():\n        raise err.TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n    # Create sample model.\n    sample_model = generators.generate_sample_model(object_type, include_optional=args.include_optional_fields)\n    # Presuming top level level model not sure how to do the typing for this.\n    sample_model.metadata.title = f'Generic {model_alias} created by trestle named {args.output}.'\n    sample_model.metadata.last_modified = datetime.now().astimezone()\n    sample_model.metadata.oscal_version = trestle.oscal.OSCAL_VERSION\n    sample_model.metadata.version = '0.0.0'\n\n    top_element = Element(sample_model, model_alias)\n\n    create_action = CreatePathAction(desired_model_path.resolve(), True)\n    write_action = WriteFileAction(\n        desired_model_path.resolve(), top_element, FileContentType.to_content_type(desired_model_path.suffix)\n    )\n\n    # create a plan to write the directory and file.\n    create_plan = Plan()\n    create_plan.add_action(create_action)\n    create_plan.add_action(write_action)\n    create_plan.execute()\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.describe/","title":"describe","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe","title":"trestle.core.commands.describe","text":"

                                    Trestle Describe Command.

                                    "},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd","title":" DescribeCmd (CommandPlusDocs) ","text":"

                                    Describe contents of a model file including optional element path.

                                    Source code in trestle/core/commands/describe.py
                                    class DescribeCmd(CommandPlusDocs):\n\"\"\"Describe contents of a model file including optional element path.\"\"\"\n\n    # The only output is via log lines.  No other results or side-effects.\n\n    name = 'describe'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument('-f', '--file', help='OSCAL file to import.', type=str, required=True)\n\n        self.add_argument(\n            '-e', '--element', help='Optional name of element in file to describe.', type=str, required=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            logger.debug('Entering trestle describe.')\n\n            log.set_log_level_from_args(args)\n\n            if args.file:\n                model_file = pathlib.Path(args.file)\n\n                element = '' if not args.element else args.element.strip(\"'\")\n                results = self.describe(model_file.resolve(), element, args.trestle_root)\n\n                return CmdReturnCodes.SUCCESS.value if len(results) > 0 else CmdReturnCodes.COMMAND_ERROR.value\n            else:\n                raise TrestleIncorrectArgsError('No file specified for command describe.')\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while describing contents of a model')\n\n    @classmethod\n    def _clean_type_string(cls, text: str) -> str:\n        text = text.replace(\"<class '\", '').replace(\"'>\", '')\n        text = text.replace('trestle.oscal.', '')\n        text = text.replace('pydantic.main.', 'stripped.')\n        return text\n\n    @classmethod\n    def _description_text(cls, sub_model: Optional[Union[OscalBaseModel, List[OscalBaseModel]]]) -> str:\n        clip_string = 100\n        if sub_model is None:\n            return 'None'\n        if type(sub_model) is list:\n            n_items = len(sub_model)\n            type_text = 'Unknown' if not n_items else f'{cls._clean_type_string(str(type(sub_model[0])))}'\n            text = f'list of {n_items} items of type {type_text}'\n            return text\n        if type(sub_model) is str:\n            return sub_model if len(sub_model\n                                    ) < clip_string else sub_model[:clip_string] + '[truncated]'  # type: ignore\n        if hasattr(sub_model, 'type_'):\n            return cls._clean_type_string(str(sub_model.type_))\n        return cls._clean_type_string(str(type(sub_model)))\n\n    @classmethod\n    def describe(cls, file_path: pathlib.Path, element_path_str: str, trestle_root: pathlib.Path) -> List[str]:\n\"\"\"Describe the contents of the file.\n\n        Args:\n            file_path: pathlib.Path Path for model file to describe.\n            element_path_str: Element path of element in model to describe.  Can be ''.\n\n        Returns:\n            The list of lines of text in the description, or an empty list on failure\n        \"\"\"\n        # figure out the model type so we can read it\n        try:\n            model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n            model: OscalBaseModel = model_type.oscal_read(file_path)\n        except TrestleError as e:\n            logger.warning(f'Error loading model {file_path} to describe: {e}')\n            return []\n\n        sub_model = model\n\n        # if an element path was provided, follow the path chain to the desired sub_model\n        if element_path_str:\n            if '*' in element_path_str or ',' in element_path_str:\n                logger.warning('Wildcards and commas are not allowed in the element path for describe.')\n                return []\n\n            if '.' not in element_path_str:\n                logger.warning('The element path for describe must either be omitted or contain at least 2 parts.')\n                return []\n\n            element_paths = utils.parse_element_arg(model, element_path_str)\n\n            sub_model_element = Element(model)\n\n            for element_path in element_paths:\n                sub_model = sub_model_element.get_at(element_path, False)\n                sub_model_element = Element(sub_model)\n\n        # now that we have the desired sub_model we can describe it\n\n        text_out: List[str] = []\n\n        # create top level text depending on whether an element path was used\n        element_text = '' if not element_path_str else f' at element path {element_path_str}'\n\n        if type(sub_model) is list:\n            text = f'Model file {file_path}{element_text} is a {cls._description_text(sub_model)}'\n            text_out.append(text)\n            logger.info(text)\n        else:\n            text = f'Model file {file_path}{element_text} is of type '\n            text += f'{cls._clean_type_string(str(type(sub_model)))} and contains:'\n            text_out.append(text)\n            logger.info(text)\n            for key in sub_model.__fields__.keys():\n                value = getattr(sub_model, key, None)\n                text = f'    {key}: {cls._description_text(value)}'\n                text_out.append(text)\n                logger.info(text)\n\n        return text_out\n
                                    "},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd.describe","title":"describe(file_path, element_path_str, trestle_root) classmethod","text":"

                                    Describe the contents of the file.

                                    Parameters:

                                    Name Type Description Default file_path Path

                                    pathlib.Path Path for model file to describe.

                                    required element_path_str str

                                    Element path of element in model to describe. Can be ''.

                                    required

                                    Returns:

                                    Type Description List[str]

                                    The list of lines of text in the description, or an empty list on failure

                                    Source code in trestle/core/commands/describe.py
                                    @classmethod\ndef describe(cls, file_path: pathlib.Path, element_path_str: str, trestle_root: pathlib.Path) -> List[str]:\n\"\"\"Describe the contents of the file.\n\n    Args:\n        file_path: pathlib.Path Path for model file to describe.\n        element_path_str: Element path of element in model to describe.  Can be ''.\n\n    Returns:\n        The list of lines of text in the description, or an empty list on failure\n    \"\"\"\n    # figure out the model type so we can read it\n    try:\n        model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n        model: OscalBaseModel = model_type.oscal_read(file_path)\n    except TrestleError as e:\n        logger.warning(f'Error loading model {file_path} to describe: {e}')\n        return []\n\n    sub_model = model\n\n    # if an element path was provided, follow the path chain to the desired sub_model\n    if element_path_str:\n        if '*' in element_path_str or ',' in element_path_str:\n            logger.warning('Wildcards and commas are not allowed in the element path for describe.')\n            return []\n\n        if '.' not in element_path_str:\n            logger.warning('The element path for describe must either be omitted or contain at least 2 parts.')\n            return []\n\n        element_paths = utils.parse_element_arg(model, element_path_str)\n\n        sub_model_element = Element(model)\n\n        for element_path in element_paths:\n            sub_model = sub_model_element.get_at(element_path, False)\n            sub_model_element = Element(sub_model)\n\n    # now that we have the desired sub_model we can describe it\n\n    text_out: List[str] = []\n\n    # create top level text depending on whether an element path was used\n    element_text = '' if not element_path_str else f' at element path {element_path_str}'\n\n    if type(sub_model) is list:\n        text = f'Model file {file_path}{element_text} is a {cls._description_text(sub_model)}'\n        text_out.append(text)\n        logger.info(text)\n    else:\n        text = f'Model file {file_path}{element_text} is of type '\n        text += f'{cls._clean_type_string(str(type(sub_model)))} and contains:'\n        text_out.append(text)\n        logger.info(text)\n        for key in sub_model.__fields__.keys():\n            value = getattr(sub_model, key, None)\n            text = f'    {key}: {cls._description_text(value)}'\n            text_out.append(text)\n            logger.info(text)\n\n    return text_out\n
                                    "},{"location":"api_reference/trestle.core.commands.href/","title":"href","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href","title":"trestle.core.commands.href","text":"

                                    Trestle Href Command.

                                    "},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd","title":" HrefCmd (CommandPlusDocs) ","text":"

                                    Change href of import in profile to point to catalog in trestle workspace.

                                    This command is needed when generating an SSP with a profile that imports a catalog from a temporary location different from the final intended location of the catalog. Omit the href argument to see the list of current imports in the profile.

                                    Source code in trestle/core/commands/href.py
                                    class HrefCmd(CommandPlusDocs):\n\"\"\"Change href of import in profile to point to catalog in trestle workspace.\n\n    This command is needed when generating an SSP with a profile that imports a catalog from a temporary\n    location different from the final intended location of the catalog.  Omit the href argument to see\n    the list of current imports in the profile.\n    \"\"\"\n\n    name = 'href'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument(\n            '-n', '--name', help='Name of trestle profile to modify (just its name).', type=str, required=True\n        )\n\n        self.add_argument(\n            '-hr',\n            '--href',\n            help='New href of form trestle://catalogs/mycat/catalog.json.',\n            type=str,\n            required=False,\n            default=''\n        )\n\n        self.add_argument(\n            '-i',\n            '--item',\n            help='Item number of href to modify.  Get list by running href with just -n <prof_name> to list values.',\n            type=int,\n            required=False,\n            default=0\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            logger.debug('Entering trestle href.')\n\n            log.set_log_level_from_args(args)\n\n            profile_name: str = args.name\n\n            new_href: str = args.href.strip(\"'\")\n\n            item_num = args.item\n\n            return self.change_import_href(args.trestle_root, profile_name, new_href, item_num)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, f'Error while changing href or import in profile: {e}')\n\n    @classmethod\n    def change_import_href(cls, trestle_root: pathlib.Path, profile_name: str, new_href: str, import_num: int) -> int:\n\"\"\"Change the href of the import in the profile to point to a catalog in a specific location.\n\n        A Profile has an Imports list containing at least one href of a catalog or profile to be imported.\n        If the item being referenced is currently in the same trestle workspace as the main profile, the original\n        href is likely different from the one needed to access the item from the profile.  Therefore,\n        in order for trestle to find the item directly from the profile, the href must be modified in a way that\n        trestle can load it.\n\n        If the item is already at the link referred to by the href as a valid URI or absolute file path then no\n        change is needed.  But if the item is being worked on in the same trestle directory as the profile,\n        the href should be modified to something like trestle://catalogs/my_catalog/catalog.json\n\n        This change only needs to be made once to the profile while the profile is being used to generate SSP's\n        from the local item, but if the final profile is released the href would need to be changed to the\n        intended final location of the referenced item.\n\n        Args:\n            trestle_root: trestle_root for this call\n            profile_name: Name of profile already imported into trestle containing href's to be changed\n            new_href: New value for the href of the import.  If blank just list the hrefs\n            import_num: Item number of the href to change.\n\n\n        Returns:\n            0 on success, 1 on failure\n\n        Assumptions and requirements:\n            The profile must be a valid profile in the trestle workspace.\n            The import must either be a valid uri, including local file, or trestle://\n            The original href is not checked and will be overwritten.\n            If href is the empty string, just list all hrefs.\n\n        Future work:\n            Allow multiple imports with matching hrefs.\n            Allow href to point to profile in trestle rather than catalog, and by name.\n            Allow full chaining of linked catalogs and profiles.\n\n        \"\"\"\n        profile_data, profile_path = load_validate_model_name(trestle_root, profile_name, Profile)\n        n_imports = len(profile_data.imports)\n        if not new_href:\n            logger.info(f'List of imports for profile {profile_name}:')\n            for ii, import_ in enumerate(profile_data.imports):\n                logger.info(f'{ii:2}: {import_.href}')\n            return CmdReturnCodes.SUCCESS.value\n        if n_imports <= import_num:\n            raise TrestleError(f'Import number {import_num} is too large.  This profile has only {n_imports} imports.')\n\n        logger.info(f'Changing import {import_num} in profile {profile_name} from, to:')\n        logger.info(f'{profile_data.imports[import_num].href}')\n        logger.info(f'{new_href}')\n        profile_data.imports[import_num].href = new_href\n        profile_data.oscal_write(profile_path)  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd.change_import_href","title":"change_import_href(trestle_root, profile_name, new_href, import_num) classmethod","text":"

                                    Change the href of the import in the profile to point to a catalog in a specific location.

                                    A Profile has an Imports list containing at least one href of a catalog or profile to be imported. If the item being referenced is currently in the same trestle workspace as the main profile, the original href is likely different from the one needed to access the item from the profile. Therefore, in order for trestle to find the item directly from the profile, the href must be modified in a way that trestle can load it.

                                    If the item is already at the link referred to by the href as a valid URI or absolute file path then no change is needed. But if the item is being worked on in the same trestle directory as the profile, the href should be modified to something like trestle://catalogs/my_catalog/catalog.json

                                    This change only needs to be made once to the profile while the profile is being used to generate SSP's from the local item, but if the final profile is released the href would need to be changed to the intended final location of the referenced item.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    trestle_root for this call

                                    required profile_name str

                                    Name of profile already imported into trestle containing href's to be changed

                                    required new_href str

                                    New value for the href of the import. If blank just list the hrefs

                                    required import_num int

                                    Item number of the href to change.

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success, 1 on failure

                                    Assumptions and requirements: The profile must be a valid profile in the trestle workspace. The import must either be a valid uri, including local file, or trestle:// The original href is not checked and will be overwritten. If href is the empty string, just list all hrefs.

                                    Future work: Allow multiple imports with matching hrefs. Allow href to point to profile in trestle rather than catalog, and by name. Allow full chaining of linked catalogs and profiles.

                                    Source code in trestle/core/commands/href.py
                                    @classmethod\ndef change_import_href(cls, trestle_root: pathlib.Path, profile_name: str, new_href: str, import_num: int) -> int:\n\"\"\"Change the href of the import in the profile to point to a catalog in a specific location.\n\n    A Profile has an Imports list containing at least one href of a catalog or profile to be imported.\n    If the item being referenced is currently in the same trestle workspace as the main profile, the original\n    href is likely different from the one needed to access the item from the profile.  Therefore,\n    in order for trestle to find the item directly from the profile, the href must be modified in a way that\n    trestle can load it.\n\n    If the item is already at the link referred to by the href as a valid URI or absolute file path then no\n    change is needed.  But if the item is being worked on in the same trestle directory as the profile,\n    the href should be modified to something like trestle://catalogs/my_catalog/catalog.json\n\n    This change only needs to be made once to the profile while the profile is being used to generate SSP's\n    from the local item, but if the final profile is released the href would need to be changed to the\n    intended final location of the referenced item.\n\n    Args:\n        trestle_root: trestle_root for this call\n        profile_name: Name of profile already imported into trestle containing href's to be changed\n        new_href: New value for the href of the import.  If blank just list the hrefs\n        import_num: Item number of the href to change.\n\n\n    Returns:\n        0 on success, 1 on failure\n\n    Assumptions and requirements:\n        The profile must be a valid profile in the trestle workspace.\n        The import must either be a valid uri, including local file, or trestle://\n        The original href is not checked and will be overwritten.\n        If href is the empty string, just list all hrefs.\n\n    Future work:\n        Allow multiple imports with matching hrefs.\n        Allow href to point to profile in trestle rather than catalog, and by name.\n        Allow full chaining of linked catalogs and profiles.\n\n    \"\"\"\n    profile_data, profile_path = load_validate_model_name(trestle_root, profile_name, Profile)\n    n_imports = len(profile_data.imports)\n    if not new_href:\n        logger.info(f'List of imports for profile {profile_name}:')\n        for ii, import_ in enumerate(profile_data.imports):\n            logger.info(f'{ii:2}: {import_.href}')\n        return CmdReturnCodes.SUCCESS.value\n    if n_imports <= import_num:\n        raise TrestleError(f'Import number {import_num} is too large.  This profile has only {n_imports} imports.')\n\n    logger.info(f'Changing import {import_num} in profile {profile_name} from, to:')\n    logger.info(f'{profile_data.imports[import_num].href}')\n    logger.info(f'{new_href}')\n    profile_data.imports[import_num].href = new_href\n    profile_data.oscal_write(profile_path)  # type: ignore\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.import_/","title":"import_","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_","title":"trestle.core.commands.import_","text":"

                                    Trestle Import Command.

                                    "},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_.ImportCmd","title":" ImportCmd (CommandPlusDocs) ","text":"

                                    Import an existing full OSCAL model into the trestle workspace.

                                    Source code in trestle/core/commands/import_.py
                                    class ImportCmd(CommandPlusDocs):\n\"\"\"Import an existing full OSCAL model into the trestle workspace.\"\"\"\n\n    name = 'import'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument(\n            '-f', '--file', help='OSCAL file to import - either file path or url.', type=str, required=True\n        )\n        self.add_argument('-o', '--output', help='Name of output element.', type=str, required=True)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Top level import run command.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = args.trestle_root\n            if not file_utils.is_valid_project_root(trestle_root):\n                raise TrestleRootError(f'Attempt to import from non-valid trestle project root {trestle_root}')\n\n            input_uri = args.file\n            if cache.FetcherFactory.in_trestle_directory(trestle_root, input_uri):\n                raise TrestleError(\n                    f'Imported file {input_uri} cannot be from current trestle project. Use duplicate instead.'\n                )\n\n            content_type = FileContentType.to_content_type('.' + input_uri.split('.')[-1])\n\n            fetcher = cache.FetcherFactory.get_fetcher(trestle_root, str(input_uri))\n\n            model_read, parent_alias = fetcher.get_oscal(True)\n\n            # validate the loaded model in memory before writing out\n            # this will do any needed fixes to the file, such as assign missing catalog group ids\n            args_validate = argparse.Namespace(mode=const.VAL_MODE_ALL)\n            validator: Validator = validator_factory.get(args_validate)\n            if not validator.model_is_valid(model_read, True, trestle_root):  # type: ignore\n                logger.warning(f'Validation of file to be imported {input_uri} did not pass.  Import failed.')\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n            plural_path = ModelUtils.model_type_to_model_dir(parent_alias)\n\n            output_name = args.output\n\n            desired_model_dir = trestle_root / plural_path\n            desired_model_path: pathlib.Path = desired_model_dir / output_name / parent_alias\n            desired_model_path = desired_model_path.with_suffix(FileContentType.to_file_extension(content_type)\n                                                                ).resolve()\n\n            if desired_model_path.exists():\n                logger.warning(f'Cannot import because file to be imported here: {desired_model_path} already exists.')\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n            if args.regenerate:\n                logger.debug(f'regenerating uuids in imported file {input_uri}')\n                model_read, lut, nchanged = ModelUtils.regenerate_uuids(model_read)\n                logger.debug(f'uuid lut has {len(lut.items())} entries and {nchanged} refs were updated')\n\n            top_element = Element(model_read)\n            create_action = CreatePathAction(desired_model_path, True)\n            write_action = WriteFileAction(desired_model_path, top_element, content_type)\n\n            # create a plan to create the directory and write the imported file.\n            import_plan = Plan()\n            import_plan.add_action(create_action)\n            import_plan.add_action(write_action)\n\n            import_plan.execute()\n\n            args = argparse.Namespace(\n                file=desired_model_path,\n                verbose=args.verbose,\n                trestle_root=args.trestle_root,\n                type=None,\n                all=None,\n                quiet=True\n            )\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while importing OSCAL file')\n
                                    "},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_.ImportCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.init/","title":"init","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init","title":"trestle.core.commands.init","text":"

                                    Trestle Init Command.

                                    "},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init.InitCmd","title":" InitCmd (CommandBase) ","text":"

                                    Initialize a trestle working directory.

                                    Source code in trestle/core/commands/init.py
                                    class InitCmd(CommandBase):\n\"\"\"Initialize a trestle working directory.\"\"\"\n\n    name = 'init'\n\n    def _init_arguments(self) -> None:\n\n        self.add_argument(const.INIT_FULL_SHORT, const.INIT_FULL_LONG, help=const.INIT_FULL_HELP, action='store_true')\n        self.add_argument(\n            const.INIT_LOCAL_SHORT, const.INIT_LOCAL_LONG, help=const.INIT_LOCAL_HELP, action='store_true'\n        )\n        self.add_argument(\n            const.INIT_GOVDOCS_SHORT, const.INIT_GOVDOCS_LONG, help=const.INIT_GOVDOCS_HELP, action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Create a trestle workspace in the current directory.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            dir_path: pathlib.Path = args.trestle_root\n            if not dir_path.exists() or not dir_path.is_dir():\n                raise TrestleRootError(\n                    f'Initialization failed. Given directory {dir_path} does not exist or is not a directory.'\n                )\n\n            if not (args.full or args.local or args.govdocs):\n                # Running in full mode by default\n                args.full = True\n\n            init_dist_folder = True if args.full else False\n            init_oscal_folders = True if args.local or args.full else False\n            copy_config_file = True if args.full or args.local else False\n\n            self._create_directories(dir_path, init_oscal_folders, init_dist_folder)\n\n            if copy_config_file:\n                self._copy_config_file(dir_path)\n\n            logger.info(f'Initialized trestle project successfully in {dir_path}')\n\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Failed to initialize Trestle working directory.')\n\n    def _create_directories(self, root: pathlib.Path, create_model_folders: bool, create_dist_folder: bool) -> None:\n\"\"\"Create the directory tree if it does not exist.\"\"\"\n        # Prepare directory list to be created\n        try:\n            directory_list = [root / pathlib.Path(const.TRESTLE_CONFIG_DIR)]\n\n            if create_model_folders:\n                for model_dir in const.MODEL_DIR_LIST:\n                    directory_list.append(root / pathlib.Path(model_dir))\n                    if create_dist_folder:\n                        directory_list.append(root / pathlib.Path(const.TRESTLE_DIST_DIR) / model_dir)\n\n            # Create directories\n            for directory in directory_list:\n                directory.mkdir(parents=True, exist_ok=True)\n                file_path = pathlib.Path(directory) / const.TRESTLE_KEEP_FILE\n                file_utils.make_hidden_file(file_path)\n        except OSError as e:\n            raise TrestleError(f'Error while creating directories: {e}')\n        except Exception as e:\n            raise TrestleError(f'Unexpected error while creating directories: {e}')\n\n    def _copy_config_file(self, root: pathlib.Path) -> None:\n\"\"\"Copy the initial config.ini file to .trestle directory.\"\"\"\n        try:\n            ref = importlib_resources.files('trestle.resources') / const.TRESTLE_CONFIG_FILE\n            with importlib_resources.as_file(ref) as source_path:\n                destination_path = (root / pathlib.Path(const.TRESTLE_CONFIG_DIR) / const.TRESTLE_CONFIG_FILE).resolve()\n                copyfile(source_path, destination_path)\n\n        except (shutil.SameFileError, OSError) as e:\n            raise TrestleError(f'Error while copying config file: {e}')\n        except Exception as e:\n            raise TrestleError(f'Unexpected error while copying config file: {e}')\n
                                    "},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init.InitCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.merge/","title":"merge","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge","title":"trestle.core.commands.merge","text":"

                                    Trestle Merge Command.

                                    "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.trace","title":"trace","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd","title":" MergeCmd (CommandPlusDocs) ","text":"

                                    Merge subcomponents on a trestle model.

                                    Source code in trestle/core/commands/merge.py
                                    class MergeCmd(CommandPlusDocs):\n\"\"\"Merge subcomponents on a trestle model.\"\"\"\n\n    name = 'merge'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=f'{const.ARG_DESC_ELEMENT}(s) to be merged. The last element is merged into the second last element.',\n            required=True\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Merge elements into the parent oscal model.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n\n            # remove any quotes passed in as on windows platforms\n            elements_clean = args.element.strip(\"'\")\n            element_paths = elements_clean.split(',')\n            trace.log(f'merge _run element paths {element_paths}')\n            cwd = Path.cwd()\n            rc = self.perform_all_merges(element_paths, cwd, args.trestle_root)\n            return rc\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while merging subcomponents on a trestle model')\n\n    @classmethod\n    def perform_all_merges(cls, element_paths: List[str], effective_cwd: Path, trestle_root: Path) -> int:\n\"\"\"Run all merges over a list of element paths.\"\"\"\n        for element_path in element_paths:\n            logger.debug(f'merge {element_path}')\n            plan = cls.merge(effective_cwd, ElementPath(element_path), trestle_root)\n            plan.execute()\n        return CmdReturnCodes.SUCCESS.value\n\n    @classmethod\n    def merge(cls, effective_cwd: Path, element_path: ElementPath, trestle_root: Path) -> Plan:\n\"\"\"Merge operations.\n\n        It returns a plan for the operation\n        \"\"\"\n        if not element_path.is_multipart():\n            raise TrestleError(\n                'Multiple parts of an element path must be passed to merge e.g. catalog.* or catalog.groups'\n            )\n\n        target_model_alias = element_path.get_last()\n        logger.debug(f'merge element path list: {element_path} target model alias {target_model_alias}')\n        # 1. Load desination model into a stripped model\n        # Load destination model\n        destination_path = element_path.get_preceding_path()\n        destination_model_alias = destination_path.get_last()\n        trace.log(f'merge destination model alias: {destination_model_alias}')\n        trace.log('merge getting contextual file type effective working directory')\n        # Destination model filetype\n        file_type = file_utils.get_contextual_file_type(effective_cwd)\n        trace.log(f'contextual file type is {file_type}')\n\n        file_ext = FileContentType.to_file_extension(file_type)\n        # Destination model filename\n        destination_model_path = (\n            effective_cwd / f'{classname_to_alias(destination_model_alias, AliasMode.JSON)}{file_ext}'\n        )\n        trace.log(f'destination model filename is {destination_model_path}')\n        destination_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root)\n\n        destination_model_object: OscalBaseModel = None\n        if destination_model_path.exists():\n            trace.log('dest filename exists so read it')\n            destination_model_object = destination_model_type.oscal_read(destination_model_path)\n        # 2. If target is wildcard, load distributed destination model and replace destination model.\n        # Handle WILDCARD '*' match. Return plan to load the destination model, with its distributed attributes\n        if target_model_alias == '*':\n            trace.log('handle target model alias wildcard')\n            collection_type = None\n            if destination_model_type.is_collection_container():\n                collection_type = destination_model_type.get_collection_type()\n\n            merged_model_type, _, merged_model_instance = ModelUtils.load_distributed(\n                destination_model_path, trestle_root, collection_type)\n            plan = Plan()\n            reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n            wrapper_alias = destination_model_alias\n            write_destination_action = WriteFileAction(\n                destination_model_path, Element(merged_model_instance, wrapper_alias), content_type=file_type\n            )\n            remove_path_folder = effective_cwd / destination_model_alias\n            delete_target_action = RemovePathAction(remove_path_folder)\n            plan: Plan = Plan()\n            plan.add_action(reset_destination_action)\n            plan.add_action(write_destination_action)\n            plan.add_action(delete_target_action)\n            return plan\n\n        trace.log(f'get dest model with fields stripped: {target_model_alias}')\n        # Get destination model without the target field stripped\n        merged_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root,\n                                                                  aliases_not_to_be_stripped=[target_model_alias])\n        # 3. Load Target model. Target model could be stripped\n        try:\n            target_model_type = element_path.get_type(merged_model_type)\n        except Exception as e:\n            logger.debug(f'target model not found, element path list {element_path} type {merged_model_type}')\n            raise TrestleError(\n                f'Target model not found. Possibly merge of the elements not allowed at this point. {str(e)}'\n            )\n        target_model_path = effective_cwd / destination_model_alias\n        trace.log(f'look for target model path {target_model_path} at dest alias {destination_model_alias} rel to cwd')\n\n        # target_model filename - depends whether destination model is decomposed or not\n        if target_model_path.exists():\n            trace.log(f'target model path does exist so target path is subdir with target alias {target_model_alias}')\n            target_model_path = target_model_path / target_model_alias\n        else:\n            trace.log(f'target model filename does not exist so target path is target alias {target_model_alias}')\n            target_model_path = target_model_path / target_model_alias  # FIXME this is same as above\n        trace.log(f'final target model path is {target_model_path}')\n\n        # if target model is a file then handle file. If file doesn't exist, handle the directory,\n        # but in this case it's a list or a dict collection type\n        target_model_filename = target_model_path.with_suffix(file_ext)\n        if target_model_filename.exists():\n            trace.log(f'target model path with extension does exist so load distrib {target_model_filename}')\n            _, _, target_model_object = ModelUtils.load_distributed(target_model_filename, trestle_root)\n        else:\n            target_model_filename = Path(target_model_path)\n            trace.log(f'target model path plus extension does not exist so load distrib {target_model_filename}')\n            trace.log(f'get collection type for model type {target_model_type}')\n            collection_type = type_utils.get_origin(target_model_type)\n            trace.log(f'load {target_model_filename} as collection type {collection_type}')\n            _, _, target_model_object = ModelUtils.load_distributed(target_model_filename,\n                                                                    trestle_root, collection_type)\n\n        if hasattr(target_model_object, '__dict__') and '__root__' in target_model_object.__dict__:\n            trace.log('loaded object has dict and root so set target model object to root contents')\n            target_model_object = target_model_object.__dict__['__root__']\n        # 4. Insert target model into destination model.\n        merged_dict = {}\n        if destination_model_object is not None:\n            merged_dict = destination_model_object.__dict__\n        merged_dict[target_model_alias] = target_model_object\n        merged_model_object = merged_model_type(**merged_dict)\n        merged_destination_element = Element(merged_model_object)\n        # 5. Create action  plan\n        trace.log(f'create path action clear content: {destination_model_path}')\n        reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n        trace.log(f'write file action {destination_model_path}')\n        write_destination_action = WriteFileAction(\n            destination_model_path, merged_destination_element, content_type=file_type\n        )\n        # FIXME this will delete metadata.json but it will leave metadata/roles/roles.*\n        # need to clean up all lower dirs\n        trace.log(f'remove path action {target_model_filename}')\n        delete_target_action = RemovePathAction(target_model_filename)\n\n        plan: Plan = Plan()\n        plan.add_action(reset_destination_action)\n        plan.add_action(write_destination_action)\n        plan.add_action(delete_target_action)\n\n        # TODO: Destination model directory is empty or already merged? Then clean up.\n\n        return plan\n
                                    "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd.merge","title":"merge(effective_cwd, element_path, trestle_root) classmethod","text":"

                                    Merge operations.

                                    It returns a plan for the operation

                                    Source code in trestle/core/commands/merge.py
                                    @classmethod\ndef merge(cls, effective_cwd: Path, element_path: ElementPath, trestle_root: Path) -> Plan:\n\"\"\"Merge operations.\n\n    It returns a plan for the operation\n    \"\"\"\n    if not element_path.is_multipart():\n        raise TrestleError(\n            'Multiple parts of an element path must be passed to merge e.g. catalog.* or catalog.groups'\n        )\n\n    target_model_alias = element_path.get_last()\n    logger.debug(f'merge element path list: {element_path} target model alias {target_model_alias}')\n    # 1. Load desination model into a stripped model\n    # Load destination model\n    destination_path = element_path.get_preceding_path()\n    destination_model_alias = destination_path.get_last()\n    trace.log(f'merge destination model alias: {destination_model_alias}')\n    trace.log('merge getting contextual file type effective working directory')\n    # Destination model filetype\n    file_type = file_utils.get_contextual_file_type(effective_cwd)\n    trace.log(f'contextual file type is {file_type}')\n\n    file_ext = FileContentType.to_file_extension(file_type)\n    # Destination model filename\n    destination_model_path = (\n        effective_cwd / f'{classname_to_alias(destination_model_alias, AliasMode.JSON)}{file_ext}'\n    )\n    trace.log(f'destination model filename is {destination_model_path}')\n    destination_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root)\n\n    destination_model_object: OscalBaseModel = None\n    if destination_model_path.exists():\n        trace.log('dest filename exists so read it')\n        destination_model_object = destination_model_type.oscal_read(destination_model_path)\n    # 2. If target is wildcard, load distributed destination model and replace destination model.\n    # Handle WILDCARD '*' match. Return plan to load the destination model, with its distributed attributes\n    if target_model_alias == '*':\n        trace.log('handle target model alias wildcard')\n        collection_type = None\n        if destination_model_type.is_collection_container():\n            collection_type = destination_model_type.get_collection_type()\n\n        merged_model_type, _, merged_model_instance = ModelUtils.load_distributed(\n            destination_model_path, trestle_root, collection_type)\n        plan = Plan()\n        reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n        wrapper_alias = destination_model_alias\n        write_destination_action = WriteFileAction(\n            destination_model_path, Element(merged_model_instance, wrapper_alias), content_type=file_type\n        )\n        remove_path_folder = effective_cwd / destination_model_alias\n        delete_target_action = RemovePathAction(remove_path_folder)\n        plan: Plan = Plan()\n        plan.add_action(reset_destination_action)\n        plan.add_action(write_destination_action)\n        plan.add_action(delete_target_action)\n        return plan\n\n    trace.log(f'get dest model with fields stripped: {target_model_alias}')\n    # Get destination model without the target field stripped\n    merged_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root,\n                                                              aliases_not_to_be_stripped=[target_model_alias])\n    # 3. Load Target model. Target model could be stripped\n    try:\n        target_model_type = element_path.get_type(merged_model_type)\n    except Exception as e:\n        logger.debug(f'target model not found, element path list {element_path} type {merged_model_type}')\n        raise TrestleError(\n            f'Target model not found. Possibly merge of the elements not allowed at this point. {str(e)}'\n        )\n    target_model_path = effective_cwd / destination_model_alias\n    trace.log(f'look for target model path {target_model_path} at dest alias {destination_model_alias} rel to cwd')\n\n    # target_model filename - depends whether destination model is decomposed or not\n    if target_model_path.exists():\n        trace.log(f'target model path does exist so target path is subdir with target alias {target_model_alias}')\n        target_model_path = target_model_path / target_model_alias\n    else:\n        trace.log(f'target model filename does not exist so target path is target alias {target_model_alias}')\n        target_model_path = target_model_path / target_model_alias  # FIXME this is same as above\n    trace.log(f'final target model path is {target_model_path}')\n\n    # if target model is a file then handle file. If file doesn't exist, handle the directory,\n    # but in this case it's a list or a dict collection type\n    target_model_filename = target_model_path.with_suffix(file_ext)\n    if target_model_filename.exists():\n        trace.log(f'target model path with extension does exist so load distrib {target_model_filename}')\n        _, _, target_model_object = ModelUtils.load_distributed(target_model_filename, trestle_root)\n    else:\n        target_model_filename = Path(target_model_path)\n        trace.log(f'target model path plus extension does not exist so load distrib {target_model_filename}')\n        trace.log(f'get collection type for model type {target_model_type}')\n        collection_type = type_utils.get_origin(target_model_type)\n        trace.log(f'load {target_model_filename} as collection type {collection_type}')\n        _, _, target_model_object = ModelUtils.load_distributed(target_model_filename,\n                                                                trestle_root, collection_type)\n\n    if hasattr(target_model_object, '__dict__') and '__root__' in target_model_object.__dict__:\n        trace.log('loaded object has dict and root so set target model object to root contents')\n        target_model_object = target_model_object.__dict__['__root__']\n    # 4. Insert target model into destination model.\n    merged_dict = {}\n    if destination_model_object is not None:\n        merged_dict = destination_model_object.__dict__\n    merged_dict[target_model_alias] = target_model_object\n    merged_model_object = merged_model_type(**merged_dict)\n    merged_destination_element = Element(merged_model_object)\n    # 5. Create action  plan\n    trace.log(f'create path action clear content: {destination_model_path}')\n    reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n    trace.log(f'write file action {destination_model_path}')\n    write_destination_action = WriteFileAction(\n        destination_model_path, merged_destination_element, content_type=file_type\n    )\n    # FIXME this will delete metadata.json but it will leave metadata/roles/roles.*\n    # need to clean up all lower dirs\n    trace.log(f'remove path action {target_model_filename}')\n    delete_target_action = RemovePathAction(target_model_filename)\n\n    plan: Plan = Plan()\n    plan.add_action(reset_destination_action)\n    plan.add_action(write_destination_action)\n    plan.add_action(delete_target_action)\n\n    # TODO: Destination model directory is empty or already merged? Then clean up.\n\n    return plan\n
                                    "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd.perform_all_merges","title":"perform_all_merges(element_paths, effective_cwd, trestle_root) classmethod","text":"

                                    Run all merges over a list of element paths.

                                    Source code in trestle/core/commands/merge.py
                                    @classmethod\ndef perform_all_merges(cls, element_paths: List[str], effective_cwd: Path, trestle_root: Path) -> int:\n\"\"\"Run all merges over a list of element paths.\"\"\"\n    for element_path in element_paths:\n        logger.debug(f'merge {element_path}')\n        plan = cls.merge(effective_cwd, ElementPath(element_path), trestle_root)\n        plan.execute()\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.partial_object_validate/","title":"partial_object_validate","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate","title":"trestle.core.commands.partial_object_validate","text":"

                                    Trestle schema-validate command.

                                    "},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate","title":" PartialObjectValidate (CommandBase) ","text":"

                                    Direct validation any oscal object in a file, including list objects.

                                    Source code in trestle/core/commands/partial_object_validate.py
                                    class PartialObjectValidate(CommandBase):\n\"\"\"Direct validation any oscal object in a file, including list objects.\"\"\"\n\n    name = 'partial-object-validate'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_FILE_SHORT}',\n            f'--{const.ARG_FILE}',\n            help=const.ARG_DESC_FILE + ' to validate',\n            required=True,\n            type=pathlib.Path\n        )\n\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=const.ARG_DESC_ELEMENT + ' to validate.',\n            required=True\n        )\n\n        self.add_argument(\n            '-nv', '--no-validators', help='Only perform the most basic validation of the file', action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            file_path: pathlib.Path = args.file.resolve()\n            if not file_path.exists() or not file_path.is_file():\n                raise TrestleError('File path provided does not exist or is a directory')\n\n            element_str: str = args.element\n            if ',' in element_str:\n                logger.warning('Only a single element path is allowed.')\n\n            return self.partial_object_validate(file_path, element_str)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while validating OSCAL file')\n\n    @classmethod\n    def partial_object_validate(cls, file_path: pathlib.Path, element_string: str) -> int:\n\"\"\"Run a schema validation on a file inferring file type based on element string.\"\"\"\n        # get model type\n        logger.info(f'Validating {file_path}')\n        element_path = elements.ElementPath(element_string)\n        # get a wrapped object\n        obm_type = element_path.get_obm_wrapped_type()\n        obm_type.oscal_read(file_path)\n\n        logger.info(f'VALID: {file_path} for {element_string}')\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate.partial_object_validate","title":"partial_object_validate(file_path, element_string) classmethod","text":"

                                    Run a schema validation on a file inferring file type based on element string.

                                    Source code in trestle/core/commands/partial_object_validate.py
                                    @classmethod\ndef partial_object_validate(cls, file_path: pathlib.Path, element_string: str) -> int:\n\"\"\"Run a schema validation on a file inferring file type based on element string.\"\"\"\n    # get model type\n    logger.info(f'Validating {file_path}')\n    element_path = elements.ElementPath(element_string)\n    # get a wrapped object\n    obm_type = element_path.get_obm_wrapped_type()\n    obm_type.oscal_read(file_path)\n\n    logger.info(f'VALID: {file_path} for {element_string}')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.remove/","title":"remove","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove","title":"trestle.core.commands.remove","text":"

                                    Trestle Remove Command.

                                    "},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd","title":" RemoveCmd (CommandPlusDocs) ","text":"

                                    Remove a subcomponent from an existing model.

                                    Source code in trestle/core/commands/remove.py
                                    class RemoveCmd(CommandPlusDocs):\n\"\"\"Remove a subcomponent from an existing model.\"\"\"\n\n    name = 'remove'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_FILE_SHORT}',\n            f'--{const.ARG_FILE}',\n            help=const.ARG_DESC_FILE + ' to remove component/subcomponent to.',\n            required=True\n        )\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=const.ARG_DESC_ELEMENT + ' to remove.',\n            required=True\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Remove an OSCAL component/subcomponent to the specified component.\n\n        This method takes input a filename and a list of comma-seperated element path. Element paths are field aliases.\n        The method first finds the parent model from the file and loads the file into the model.\n        Then the method executes 'remove' for each of the element paths specified.\n        \"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            args_dict = args.__dict__\n\n            file_path = pathlib.Path(args_dict[const.ARG_FILE]).resolve()\n            relative_path = file_path.relative_to(args.trestle_root)\n            # Get parent model and then load json into parent model\n            parent_model, parent_alias = ModelUtils.get_relative_model_type(relative_path)\n\n            parent_object = parent_model.oscal_read(file_path)\n            parent_element = Element(parent_object, parent_alias)\n\n            add_plan = Plan()\n\n            # Do _remove for each element_path specified in args\n            element_paths: List[str] = str(args_dict[const.ARG_ELEMENT]).split(',')\n            for elm_path_str in element_paths:\n                element_path = ElementPath(elm_path_str)\n                remove_action, parent_element = self.remove(element_path, parent_element)\n                add_plan.add_action(remove_action)\n\n            create_action = CreatePathAction(file_path, True)\n            write_action = WriteFileAction(file_path, parent_element, FileContentType.to_content_type(file_path.suffix))\n            add_plan.add_action(remove_action)\n            add_plan.add_action(create_action)\n            add_plan.add_action(write_action)\n\n            add_plan.execute()\n\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:\n            return err.handle_generic_command_exception(e, logger, 'Error while removing OSCAL component')\n\n    @classmethod\n    def remove(cls, element_path: ElementPath, parent_element: Element) -> Tuple[RemoveAction, Element]:\n\"\"\"For the element_path, remove a model from the parent_element of a given parent_model.\n\n        First we check if there is an existing element at that path\n        If not, we complain.\n        Then we set up an action plan to update the model (specified by file_path) in memory,\n        return the action and return the parent_element.\n\n        LIMITATIONS:\n        1. This does not remove elements of a list or dict. Instead, the entire list or dict is removed.\n        2. This cannot remove arbitrarily named elements that are not specified in the schema.\n        For example, \"responsible-parties\" contains named elements, e.g., \"organisation\". The tool will not\n        remove the \"organisation\" as it is not in the schema, but one can remove its elements, e.g., \"party-uuids\".\n        \"\"\"\n        element_path_list = element_path.get_full_path_parts()\n        if '*' in element_path_list:\n            raise err.TrestleError('trestle remove does not support Wildcard element path.')\n\n        deleting_element = parent_element.get_at(element_path)\n\n        if deleting_element is not None:\n            # The element already exists\n            if type(deleting_element) is list:\n                logger.warning(\n                    'Warning: trestle remove does not support removing elements of a list: '\n                    'this removes the entire list'\n                )\n            elif type(deleting_element) is dict:\n                logger.warning(\n                    'Warning: trestle remove does not support removing dict elements: '\n                    'this removes the entire dict element'\n                )\n        else:\n            raise err.TrestleError(f'Bad element path: {str(element_path)}')\n\n        remove_action = RemoveAction(parent_element, element_path)\n\n        return remove_action, parent_element\n
                                    "},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd.remove","title":"remove(element_path, parent_element) classmethod","text":"

                                    For the element_path, remove a model from the parent_element of a given parent_model.

                                    First we check if there is an existing element at that path If not, we complain. Then we set up an action plan to update the model (specified by file_path) in memory, return the action and return the parent_element.

                                    LIMITATIONS: 1. This does not remove elements of a list or dict. Instead, the entire list or dict is removed. 2. This cannot remove arbitrarily named elements that are not specified in the schema. For example, \"responsible-parties\" contains named elements, e.g., \"organisation\". The tool will not remove the \"organisation\" as it is not in the schema, but one can remove its elements, e.g., \"party-uuids\".

                                    Source code in trestle/core/commands/remove.py
                                    @classmethod\ndef remove(cls, element_path: ElementPath, parent_element: Element) -> Tuple[RemoveAction, Element]:\n\"\"\"For the element_path, remove a model from the parent_element of a given parent_model.\n\n    First we check if there is an existing element at that path\n    If not, we complain.\n    Then we set up an action plan to update the model (specified by file_path) in memory,\n    return the action and return the parent_element.\n\n    LIMITATIONS:\n    1. This does not remove elements of a list or dict. Instead, the entire list or dict is removed.\n    2. This cannot remove arbitrarily named elements that are not specified in the schema.\n    For example, \"responsible-parties\" contains named elements, e.g., \"organisation\". The tool will not\n    remove the \"organisation\" as it is not in the schema, but one can remove its elements, e.g., \"party-uuids\".\n    \"\"\"\n    element_path_list = element_path.get_full_path_parts()\n    if '*' in element_path_list:\n        raise err.TrestleError('trestle remove does not support Wildcard element path.')\n\n    deleting_element = parent_element.get_at(element_path)\n\n    if deleting_element is not None:\n        # The element already exists\n        if type(deleting_element) is list:\n            logger.warning(\n                'Warning: trestle remove does not support removing elements of a list: '\n                'this removes the entire list'\n            )\n        elif type(deleting_element) is dict:\n            logger.warning(\n                'Warning: trestle remove does not support removing dict elements: '\n                'this removes the entire dict element'\n            )\n    else:\n        raise err.TrestleError(f'Bad element path: {str(element_path)}')\n\n    remove_action = RemoveAction(parent_element, element_path)\n\n    return remove_action, parent_element\n
                                    "},{"location":"api_reference/trestle.core.commands.replicate/","title":"replicate","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate","title":"trestle.core.commands.replicate","text":"

                                    Trestle Replicate Command.

                                    "},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd","title":" ReplicateCmd (CommandPlusDocs) ","text":"

                                    Replicate a top level model within the trestle directory structure.

                                    Source code in trestle/core/commands/replicate.py
                                    class ReplicateCmd(CommandPlusDocs):\n\"\"\"Replicate a top level model within the trestle directory structure.\"\"\"\n\n    name = 'replicate'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n\n        self.add_argument('model', help='Choose OSCAL model', choices=const.MODEL_TYPE_LIST)\n        self.add_argument('-n', '--name', help='Name of model to replicate.', type=str, required=True)\n        self.add_argument('-o', '--output', help='Name of replicated model.', type=str, required=True)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Execute and process the args.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            return self.replicate_object(args.model, args)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while replicating model')\n\n    @classmethod\n    def replicate_object(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"\n        Core replicate routine invoked by subcommands.\n\n        Args:\n            model_alias: Name of the top level model in the trestle directory.\n            args: CLI arguments\n        Returns:\n            A return code that can be used as standard posix codes. 0 is success.\n        \"\"\"\n        logger.debug('Entering replicate_object.')\n\n        # 1 Bad working directory if not running from current working directory\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n        if not trestle_root or not file_utils.is_valid_project_root(trestle_root):\n            raise TrestleError(f'Given directory: {trestle_root} is not a trestle project.')\n\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n        # 2 Check that input file given exists.\n\n        input_file_stem = trestle_root / plural_path / args.name / model_alias\n        content_type = FileContentType.path_to_content_type(input_file_stem)\n        if content_type == FileContentType.UNKNOWN:\n            raise TrestleError(\n                f'Input file {args.name} has no json or yaml file at expected location {input_file_stem}.'\n            )\n\n        input_file = input_file_stem.with_suffix(FileContentType.to_file_extension(content_type))\n\n        # 3 Distributed load from file\n        _, model_alias, model_instance = ModelUtils.load_distributed(input_file, trestle_root)\n\n        rep_model_path = trestle_root / plural_path / args.output / (\n            model_alias + FileContentType.to_file_extension(content_type)\n        )\n\n        if rep_model_path.exists():\n            raise TrestleError(f'OSCAL file to be replicated here: {rep_model_path} exists.')\n\n        if args.regenerate:\n            logger.debug(f'regenerating uuids for model {input_file}')\n            model_instance, uuid_lut, n_refs_updated = ModelUtils.regenerate_uuids(model_instance)\n            logger.debug(f'{len(uuid_lut)} uuids generated and {n_refs_updated} references updated')\n\n        # 4 Prepare actions and plan\n        top_element = Element(model_instance)\n        create_action = CreatePathAction(rep_model_path, True)\n        write_action = WriteFileAction(rep_model_path, top_element, content_type)\n\n        # create a plan to create the directory and imported file.\n        replicate_plan = Plan()\n        replicate_plan.add_action(create_action)\n        replicate_plan.add_action(write_action)\n\n        replicate_plan.execute()\n\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd.replicate_object","title":"replicate_object(model_alias, args) classmethod","text":"

                                    Core replicate routine invoked by subcommands.

                                    Parameters:

                                    Name Type Description Default model_alias str

                                    Name of the top level model in the trestle directory.

                                    required args Namespace

                                    CLI arguments

                                    required

                                    Returns:

                                    Type Description int

                                    A return code that can be used as standard posix codes. 0 is success.

                                    Source code in trestle/core/commands/replicate.py
                                    @classmethod\ndef replicate_object(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"\n    Core replicate routine invoked by subcommands.\n\n    Args:\n        model_alias: Name of the top level model in the trestle directory.\n        args: CLI arguments\n    Returns:\n        A return code that can be used as standard posix codes. 0 is success.\n    \"\"\"\n    logger.debug('Entering replicate_object.')\n\n    # 1 Bad working directory if not running from current working directory\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n    if not trestle_root or not file_utils.is_valid_project_root(trestle_root):\n        raise TrestleError(f'Given directory: {trestle_root} is not a trestle project.')\n\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n    # 2 Check that input file given exists.\n\n    input_file_stem = trestle_root / plural_path / args.name / model_alias\n    content_type = FileContentType.path_to_content_type(input_file_stem)\n    if content_type == FileContentType.UNKNOWN:\n        raise TrestleError(\n            f'Input file {args.name} has no json or yaml file at expected location {input_file_stem}.'\n        )\n\n    input_file = input_file_stem.with_suffix(FileContentType.to_file_extension(content_type))\n\n    # 3 Distributed load from file\n    _, model_alias, model_instance = ModelUtils.load_distributed(input_file, trestle_root)\n\n    rep_model_path = trestle_root / plural_path / args.output / (\n        model_alias + FileContentType.to_file_extension(content_type)\n    )\n\n    if rep_model_path.exists():\n        raise TrestleError(f'OSCAL file to be replicated here: {rep_model_path} exists.')\n\n    if args.regenerate:\n        logger.debug(f'regenerating uuids for model {input_file}')\n        model_instance, uuid_lut, n_refs_updated = ModelUtils.regenerate_uuids(model_instance)\n        logger.debug(f'{len(uuid_lut)} uuids generated and {n_refs_updated} references updated')\n\n    # 4 Prepare actions and plan\n    top_element = Element(model_instance)\n    create_action = CreatePathAction(rep_model_path, True)\n    write_action = WriteFileAction(rep_model_path, top_element, content_type)\n\n    # create a plan to create the directory and imported file.\n    replicate_plan = Plan()\n    replicate_plan.add_action(create_action)\n    replicate_plan.add_action(write_action)\n\n    replicate_plan.execute()\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.split/","title":"split","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split","title":"trestle.core.commands.split","text":"

                                    Trestle Split Command.

                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.trace","title":"trace","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker","title":" AliasTracker (TrestleBaseModel) pydantic-model","text":"

                                    Convenience class to track writing out of models.

                                    Source code in trestle/core/commands/split.py
                                    class AliasTracker(TrestleBaseModel):\n\"\"\"Convenience class to track writing out of models.\"\"\"\n\n    # This tracks the parts that need to be split from each element\n    # and makes sure it is written out once\n\n    aliases: List[str]\n    written: bool = False\n\n    def add_alias(self, alias: str) -> None:\n\"\"\"Add alias.\"\"\"\n        if alias not in self.aliases:\n            self.aliases.append(alias)\n\n    def get_aliases(self) -> List[str]:\n\"\"\"Get the list of aliases.\"\"\"\n        return self.aliases\n\n    def needs_writing(self) -> bool:\n\"\"\"Need to write the model.\"\"\"\n        return not self.written\n\n    def mark_written(self) -> None:\n\"\"\"Mark this model as written.\"\"\"\n        self.written = True\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.aliases","title":"aliases: List[str] pydantic-field required","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.written","title":"written: bool pydantic-field","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.add_alias","title":"add_alias(self, alias)","text":"

                                    Add alias.

                                    Source code in trestle/core/commands/split.py
                                    def add_alias(self, alias: str) -> None:\n\"\"\"Add alias.\"\"\"\n    if alias not in self.aliases:\n        self.aliases.append(alias)\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.get_aliases","title":"get_aliases(self)","text":"

                                    Get the list of aliases.

                                    Source code in trestle/core/commands/split.py
                                    def get_aliases(self) -> List[str]:\n\"\"\"Get the list of aliases.\"\"\"\n    return self.aliases\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.mark_written","title":"mark_written(self)","text":"

                                    Mark this model as written.

                                    Source code in trestle/core/commands/split.py
                                    def mark_written(self) -> None:\n\"\"\"Mark this model as written.\"\"\"\n    self.written = True\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.needs_writing","title":"needs_writing(self)","text":"

                                    Need to write the model.

                                    Source code in trestle/core/commands/split.py
                                    def needs_writing(self) -> bool:\n\"\"\"Need to write the model.\"\"\"\n    return not self.written\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd","title":" SplitCmd (CommandPlusDocs) ","text":"

                                    Split subcomponents on a trestle model.

                                    Source code in trestle/core/commands/split.py
                                    class SplitCmd(CommandPlusDocs):\n\"\"\"Split subcomponents on a trestle model.\"\"\"\n\n    name = 'split'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_FILE_SHORT}', f'--{const.ARG_FILE}', help=const.ARG_DESC_FILE + ' to split.', required=False\n        )\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=const.ARG_DESC_ELEMENT + ' to split.',\n            required=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Split an OSCAL file into elements.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            trace.log('Entering trestle split.')\n            # get the Model\n            args_raw: Dict[str, str] = args.__dict__\n\n            # remove any quotes passed in as on windows platforms\n            elements_clean: str = args_raw[const.ARG_ELEMENT].strip(\"'\")\n\n            file_name = ''\n            file_name = '' if not args_raw[const.ARG_FILE] else args_raw[const.ARG_FILE]\n            # cwd must be in the model directory if file to split is not specified\n            effective_cwd = pathlib.Path.cwd()\n\n            return self.perform_split(effective_cwd, file_name, elements_clean, args.trestle_root)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while performing a split operation')\n\n    @classmethod\n    def perform_split(\n        cls, effective_cwd: pathlib.Path, file_name: str, elements: str, trestle_root: pathlib.Path\n    ) -> int:\n\"\"\"Perform the split operation.\n\n        Args:\n            effective_cwd: effective directory in which the the split operation is performed\n            file_name: file name of model to split, or '' if deduced from elements and cwd\n            elements: comma separated list of paths to strip from the file, with quotes removed\n\n        Returns:\n            0 on success and 1 on failure\n        \"\"\"\n        file_path_list: List[Tuple[str, str]] = []\n\n        if file_name:\n            file_path_list.append((file_name, elements))\n        else:\n            # cwd must be in the model directory if file to split is not specified\n            # find top directory for this model based on trestle root and cwd\n            model_dir = file_utils.extract_project_model_path(effective_cwd)\n            if model_dir is None:\n                raise TrestleError('Current directory must be within a model directory if file is not specified')\n\n            content_type: FileContentType = FileContentType.dir_to_content_type(model_dir)\n\n            # determine the file needed for each split path\n            element_paths = elements.split(',')\n            for path in element_paths:\n                element_path = ElementPath(path)\n                # if element path is relative use directory context to determine absolute path\n                element_path.make_absolute(model_dir, effective_cwd)\n                file_path = element_path.find_last_file_in_path(content_type, model_dir)\n                # now make the element path relative to the model file to be loaded\n                if file_path is None or element_path.make_relative(file_path.relative_to(model_dir)) != 0:\n                    raise TrestleError(f'Unable to match element path with files in model directory {element_path}')\n\n                file_path_list.append((file_path, element_path.to_string()))\n\n        # match paths to corresponding files since several paths may be split from the same file\n        file_path_dict: Dict[str, str] = {}\n        for file_path in file_path_list:\n            key = file_path[0]  # type: ignore\n            path = file_path[1]  # type: ignore\n            if key not in file_path_dict:\n                file_path_dict[key] = path\n            else:\n                current_path = file_path_dict[key]\n                file_path_dict[key] = f'{current_path},{path}'\n\n        for raw_file_name, element_path in file_path_dict.items():\n            file_path = file_utils.relative_resolve(pathlib.Path(raw_file_name), effective_cwd)\n            # this makes assumptions that the path is relative.\n            if not file_path.exists():\n                raise TrestleError(f'File {file_path} does not exist.')\n\n            content_type = FileContentType.to_content_type(file_path.suffix)\n\n            # find the base directory of the file\n            base_dir = file_path.parent\n            model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n\n            model: OscalBaseModel = model_type.oscal_read(file_path)\n\n            if cmd_utils.split_is_too_fine(element_path, model):\n                raise TrestleError('Cannot split the model to the level of uuids, strings, etc.')\n\n            # use the model itself to resolve any wildcards and create list of element paths\n            logger.debug(f'split calling parse_element_args on {element_path}')\n            # use contextual mode to parse\n\n            element_paths: List[ElementPath] = cmd_utils.parse_element_args(\n                model, element_path.split(','), base_dir.relative_to(trestle_root)\n            )\n\n            # analyze the split tree and determine which aliases should be stripped from each file\n            aliases_to_strip = cls.find_aliases_to_strip(element_paths)\n\n            # need the file name relative to the base directory\n            file_name_no_path = str(file_path.name)\n\n            split_plan = cls.split_model(\n                model, element_paths, base_dir, content_type, file_name_no_path, aliases_to_strip\n            )\n            trash.store(file_path, True)\n\n            try:\n                split_plan.execute()\n            except Exception as e:\n                trash.recover(file_path, True)\n                raise TrestleError(f'Split has failed with error: {e}.')\n\n        return CmdReturnCodes.SUCCESS.value\n\n    @classmethod\n    def prepare_sub_model_split_actions(\n        cls,\n        sub_model_item: OscalBaseModel,\n        sub_model_dir: pathlib.Path,\n        file_prefix: str,\n        content_type: FileContentType\n    ) -> List[Action]:\n\"\"\"Create split actions of sub model.\"\"\"\n        actions: List[Action] = []\n        file_name = cmd_utils.to_model_file_name(sub_model_item, file_prefix, content_type)\n        model_type = classname_to_alias(type(sub_model_item).__name__, AliasMode.JSON)\n        sub_model_file = sub_model_dir / file_name\n        actions.append(CreatePathAction(sub_model_file))\n        actions.append(WriteFileAction(sub_model_file, Element(sub_model_item, model_type), content_type))\n        return actions\n\n    @classmethod\n    def split_model_at_path_chain(\n        cls,\n        model_obj: OscalBaseModel,\n        element_paths: List[ElementPath],\n        base_dir: pathlib.Path,\n        content_type: FileContentType,\n        cur_path_index: int,\n        split_plan: Plan,\n        strip_root: bool,\n        root_file_name: str,\n        aliases_to_strip: Dict[str, AliasTracker],\n        last_one: bool = True\n    ) -> int:\n\"\"\"Recursively split the model at the provided chain of element paths.\n\n        It assumes that a chain of element paths starts at the cur_path_index with the first path ending\n        with a wildcard (*)\n\n        If the wildcard follows an element that is inherently a list of items, the list of items is extracted.\n        But if the wildcard follows a generic model than members of that model class found in the model will be\n        split off.  But only the non-trivial elements are removed, i.e. not str, int, datetime, etc.\n\n        Args:\n            model_obj: The OscalBaseModel to be split\n            element_paths: The List[ElementPath] of elements to split, including embedded wildcards\n            base_dir: pathlib.Path of the file being split\n            content_type: json or yaml files\n            cur_path_index: Index into the list of element paths for the current split operation\n            split_plan: The accumulated plan of actions needed to perform the split\n            strip_root: Whether to strip elements from the root object\n            root_file_name: Filename of root file that gets split into a list of items\n            aliases_to_strip: AliasTracker previously loaded with aliases that need to be split from each element\n            last_one: bool indicating last item in array has been split and stripped model can now be written\n\n        Returns:\n            int representing the index where the chain of the path ends.\n\n        Examples:\n            For example, element paths could have a list of paths as below for a `ComponentDefinition` model where\n            the first path is the start of the chain.\n\n            For each of the sub model described by the first element path (e.g component-defintion.components.*) in the\n            chain, the subsequent paths (e.g component.control-implementations.*) will be applied recursively\n            to retrieve the sub-sub models:\n            [\n                'component-definition.component.*',\n                'component.control-implementations.*'\n            ]\n            for a command like below:\n            trestle split -f component.yaml -e component-definition.components.*.control-implementations.*\n        \"\"\"\n        if split_plan is None:\n            raise TrestleError('Split plan must have been initialized')\n\n        if cur_path_index < 0:\n            raise TrestleError('Current index of the chain of paths cannot be less than 0')\n\n        # if there are no more element_paths, return the current plan\n        if cur_path_index >= len(element_paths):\n            return cur_path_index\n\n        # initialize local variables\n        element = Element(model_obj)\n        stripped_field_alias: List[str] = []\n\n        # get the sub_model specified by the element_path of this round\n        element_path = element_paths[cur_path_index]\n\n        # does the next element_path point back at me\n        is_parent = cur_path_index + 1 < len(element_paths) and element_paths[cur_path_index\n                                                                              + 1].get_parent() == element_path\n\n        # root dir name for sub models dir\n        # 00000__group.json will have the root_dir name as 00000__group for sub models of group\n        # catalog.json will have the root_dir name as catalog\n        root_dir = ''\n        if root_file_name != '':\n            root_dir = str(pathlib.Path(root_file_name).with_suffix(''))\n\n        sub_models = element.get_at(element_path, False)  # we call sub_models as in plural, but it can be just one\n\n        # assume cur_path_index is the end of the chain\n        # value of this variable may change during recursive split of the sub-models below\n        path_chain_end = cur_path_index\n\n        # if wildcard is present in the element_path and the next path in the chain has current path as the parent,\n        # Then deal with case of list, or split of arbitrary oscalbasemodel\n        if is_parent and element_path.get_last() is not ElementPath.WILDCARD:\n            # create dir for all sub model items\n            sub_models_dir = base_dir / element_path.to_root_path()\n            sub_model_plan = Plan()\n            path_chain_end = cls.split_model_at_path_chain(\n                sub_models,\n                element_paths,\n                sub_models_dir,\n                content_type,\n                cur_path_index + 1,\n                sub_model_plan,\n                True,\n                '',\n                aliases_to_strip\n            )\n            sub_model_actions = sub_model_plan.get_actions()\n            split_plan.add_actions(sub_model_actions)\n        elif element_path.get_last() == ElementPath.WILDCARD:\n            # extract sub-models into a dict with appropriate prefix\n            sub_model_items: Dict[str, OscalBaseModel] = {}\n            sub_models_dir = base_dir / element_path.to_file_path(root_dir=root_dir)\n            if isinstance(sub_models, list):\n                for i, sub_model_item in enumerate(sub_models):\n                    # e.g. `groups/00000_groups/`\n                    prefix = str(i).zfill(const.FILE_DIGIT_PREFIX_LENGTH)\n                    sub_model_items[prefix] = sub_model_item\n\n            # process list sub model items\n            count = 0\n            for key, sub_model_item in sub_model_items.items():\n                count += 1\n                # recursively split the sub-model if there are more element paths to traverse\n                # e.g. split component.control-implementations.*\n                require_recursive_split = cur_path_index + 1 < len(element_paths) and element_paths[\n                    cur_path_index + 1].get_parent() == element_path\n\n                if require_recursive_split:\n                    # prepare individual directory for each sub-model\n                    sub_root_file_name = cmd_utils.to_model_file_name(sub_model_item, key, content_type)\n                    sub_model_plan = Plan()\n\n                    last_one: bool = count == len(sub_model_items)\n                    path_chain_end = cls.split_model_at_path_chain(\n                        sub_model_item,\n                        element_paths,\n                        sub_models_dir,\n                        content_type,\n                        cur_path_index + 1,\n                        sub_model_plan,\n                        True,\n                        sub_root_file_name,\n                        aliases_to_strip,\n                        last_one\n                    )\n                    sub_model_actions = sub_model_plan.get_actions()\n                else:\n                    sub_model_actions = cls.prepare_sub_model_split_actions(\n                        sub_model_item, sub_models_dir, key, content_type\n                    )\n\n                split_plan.add_actions(sub_model_actions)\n        else:\n            # the chain of path ends at the current index.\n            # so no recursive call. Let's just write the sub model to the file and get out\n            if sub_models is not None:\n                sub_model_file = base_dir / element_path.to_file_path(content_type, root_dir=root_dir)\n                split_plan.add_action(CreatePathAction(sub_model_file))\n                split_plan.add_action(\n                    WriteFileAction(sub_model_file, Element(sub_models, element_path.get_element_name()), content_type)\n                )\n\n        # Strip the root model and add a WriteAction for the updated model object in the plan\n        if strip_root:\n            full_path = element_path.get_full()\n            path = '.'.join(full_path.split('.')[:-1])\n            aliases = [element_path.get_element_name()]\n            need_to_write = True\n            use_alias_dict = aliases_to_strip is not None and path in aliases_to_strip\n            if use_alias_dict:\n                aliases = aliases_to_strip[path].get_aliases()\n                need_to_write = aliases_to_strip[path].needs_writing()\n\n            stripped_model = model_obj.stripped_instance(stripped_fields_aliases=aliases)\n            # can mark it written even if it doesn't need writing since it is empty\n            # but if an array only mark it written if it's the last one\n            if last_one and use_alias_dict:\n                aliases_to_strip[path].mark_written()\n            # If it's an empty model after stripping the fields, don't create path and don't write\n            field_list = [x for x in model_obj.__fields__.keys() if model_obj.__fields__[x] is not None]\n            if set(field_list) == set(stripped_field_alias):\n                return path_chain_end\n\n            if need_to_write:\n                if root_file_name != '':\n                    root_file = base_dir / root_file_name\n                else:\n                    root_file = base_dir / element_path.to_root_path(content_type)\n\n                split_plan.add_action(CreatePathAction(root_file))\n                wrapper_alias = classname_to_alias(stripped_model.__class__.__name__, AliasMode.JSON)\n                split_plan.add_action(WriteFileAction(root_file, Element(stripped_model, wrapper_alias), content_type))\n\n        # return the end of the current path chain\n        return path_chain_end\n\n    @classmethod\n    def split_model(\n        cls,\n        model_obj: OscalBaseModel,\n        element_paths: List[ElementPath],\n        base_dir: pathlib.Path,\n        content_type: FileContentType,\n        root_file_name: str,\n        aliases_to_strip: Dict[str, AliasTracker]\n    ) -> Plan:\n\"\"\"Split the model at the provided element paths.\n\n        It returns a plan for the operation\n        \"\"\"\n        # initialize plan\n        split_plan = Plan()\n\n        # loop through the element path list and update the split_plan\n        stripped_field_alias = []\n        cur_path_index = 0\n        while cur_path_index < len(element_paths):\n            # extract the sub element name for each of the root path of the path chain\n            element_path = element_paths[cur_path_index]\n\n            if element_path.get_parent() is None and len(element_path.get()) > 1:\n                stripped_part = element_path.get()[1]\n                if stripped_part == ElementPath.WILDCARD:\n                    stripped_field_alias.append('__root__')\n                else:\n                    if stripped_part not in stripped_field_alias:\n                        stripped_field_alias.append(stripped_part)\n\n            # split model at the path chain\n            cur_path_index = cls.split_model_at_path_chain(\n                model_obj,\n                element_paths,\n                base_dir,\n                content_type,\n                cur_path_index,\n                split_plan,\n                False,\n                root_file_name,\n                aliases_to_strip\n            )\n\n            cur_path_index += 1\n\n        # strip the root model object and add a WriteAction\n        stripped_root = model_obj.stripped_instance(stripped_fields_aliases=stripped_field_alias)\n        # If it's an empty model after stripping the fields, don't create path and don't write\n        if set(model_obj.__fields__.keys()) == set(stripped_field_alias):\n            return split_plan\n        if root_file_name != '':\n            root_file = base_dir / root_file_name\n        else:\n            root_file = base_dir / element_paths[0].to_root_path(content_type)\n        split_plan.add_action(CreatePathAction(root_file, True))\n        wrapper_alias = classname_to_alias(stripped_root.__class__.__name__, AliasMode.JSON)\n        split_plan.add_action(WriteFileAction(root_file, Element(stripped_root, wrapper_alias), content_type))\n\n        return split_plan\n\n    @classmethod\n    def find_aliases_to_strip(cls, element_paths: List[ElementPath]) -> Dict[str, AliasTracker]:\n\"\"\"Find list of aliases that need to be stripped as each element written out.\"\"\"\n        # A given path may be present in several split actions\n        # Need to determine all parts stripped at each node in order to strip them all and\n        # write the stripped model only once\n        tracker_map: Dict[str, AliasTracker] = {}\n        for element_path in element_paths:\n            path = element_path.get_full()\n            path_parts = path.split('.')\n            alias = path_parts[-1]\n            if len(path_parts) > 2 and alias != '*':\n                root_path = '.'.join(path_parts[:-1])\n                if root_path in tracker_map:\n                    tracker_map[root_path].add_alias(alias)\n                else:\n                    tracker_map[root_path] = AliasTracker(aliases=[alias])\n        return tracker_map\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.find_aliases_to_strip","title":"find_aliases_to_strip(element_paths) classmethod","text":"

                                    Find list of aliases that need to be stripped as each element written out.

                                    Source code in trestle/core/commands/split.py
                                    @classmethod\ndef find_aliases_to_strip(cls, element_paths: List[ElementPath]) -> Dict[str, AliasTracker]:\n\"\"\"Find list of aliases that need to be stripped as each element written out.\"\"\"\n    # A given path may be present in several split actions\n    # Need to determine all parts stripped at each node in order to strip them all and\n    # write the stripped model only once\n    tracker_map: Dict[str, AliasTracker] = {}\n    for element_path in element_paths:\n        path = element_path.get_full()\n        path_parts = path.split('.')\n        alias = path_parts[-1]\n        if len(path_parts) > 2 and alias != '*':\n            root_path = '.'.join(path_parts[:-1])\n            if root_path in tracker_map:\n                tracker_map[root_path].add_alias(alias)\n            else:\n                tracker_map[root_path] = AliasTracker(aliases=[alias])\n    return tracker_map\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.perform_split","title":"perform_split(effective_cwd, file_name, elements, trestle_root) classmethod","text":"

                                    Perform the split operation.

                                    Parameters:

                                    Name Type Description Default effective_cwd Path

                                    effective directory in which the the split operation is performed

                                    required file_name str

                                    file name of model to split, or '' if deduced from elements and cwd

                                    required elements str

                                    comma separated list of paths to strip from the file, with quotes removed

                                    required

                                    Returns:

                                    Type Description int

                                    0 on success and 1 on failure

                                    Source code in trestle/core/commands/split.py
                                    @classmethod\ndef perform_split(\n    cls, effective_cwd: pathlib.Path, file_name: str, elements: str, trestle_root: pathlib.Path\n) -> int:\n\"\"\"Perform the split operation.\n\n    Args:\n        effective_cwd: effective directory in which the the split operation is performed\n        file_name: file name of model to split, or '' if deduced from elements and cwd\n        elements: comma separated list of paths to strip from the file, with quotes removed\n\n    Returns:\n        0 on success and 1 on failure\n    \"\"\"\n    file_path_list: List[Tuple[str, str]] = []\n\n    if file_name:\n        file_path_list.append((file_name, elements))\n    else:\n        # cwd must be in the model directory if file to split is not specified\n        # find top directory for this model based on trestle root and cwd\n        model_dir = file_utils.extract_project_model_path(effective_cwd)\n        if model_dir is None:\n            raise TrestleError('Current directory must be within a model directory if file is not specified')\n\n        content_type: FileContentType = FileContentType.dir_to_content_type(model_dir)\n\n        # determine the file needed for each split path\n        element_paths = elements.split(',')\n        for path in element_paths:\n            element_path = ElementPath(path)\n            # if element path is relative use directory context to determine absolute path\n            element_path.make_absolute(model_dir, effective_cwd)\n            file_path = element_path.find_last_file_in_path(content_type, model_dir)\n            # now make the element path relative to the model file to be loaded\n            if file_path is None or element_path.make_relative(file_path.relative_to(model_dir)) != 0:\n                raise TrestleError(f'Unable to match element path with files in model directory {element_path}')\n\n            file_path_list.append((file_path, element_path.to_string()))\n\n    # match paths to corresponding files since several paths may be split from the same file\n    file_path_dict: Dict[str, str] = {}\n    for file_path in file_path_list:\n        key = file_path[0]  # type: ignore\n        path = file_path[1]  # type: ignore\n        if key not in file_path_dict:\n            file_path_dict[key] = path\n        else:\n            current_path = file_path_dict[key]\n            file_path_dict[key] = f'{current_path},{path}'\n\n    for raw_file_name, element_path in file_path_dict.items():\n        file_path = file_utils.relative_resolve(pathlib.Path(raw_file_name), effective_cwd)\n        # this makes assumptions that the path is relative.\n        if not file_path.exists():\n            raise TrestleError(f'File {file_path} does not exist.')\n\n        content_type = FileContentType.to_content_type(file_path.suffix)\n\n        # find the base directory of the file\n        base_dir = file_path.parent\n        model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n\n        model: OscalBaseModel = model_type.oscal_read(file_path)\n\n        if cmd_utils.split_is_too_fine(element_path, model):\n            raise TrestleError('Cannot split the model to the level of uuids, strings, etc.')\n\n        # use the model itself to resolve any wildcards and create list of element paths\n        logger.debug(f'split calling parse_element_args on {element_path}')\n        # use contextual mode to parse\n\n        element_paths: List[ElementPath] = cmd_utils.parse_element_args(\n            model, element_path.split(','), base_dir.relative_to(trestle_root)\n        )\n\n        # analyze the split tree and determine which aliases should be stripped from each file\n        aliases_to_strip = cls.find_aliases_to_strip(element_paths)\n\n        # need the file name relative to the base directory\n        file_name_no_path = str(file_path.name)\n\n        split_plan = cls.split_model(\n            model, element_paths, base_dir, content_type, file_name_no_path, aliases_to_strip\n        )\n        trash.store(file_path, True)\n\n        try:\n            split_plan.execute()\n        except Exception as e:\n            trash.recover(file_path, True)\n            raise TrestleError(f'Split has failed with error: {e}.')\n\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.prepare_sub_model_split_actions","title":"prepare_sub_model_split_actions(sub_model_item, sub_model_dir, file_prefix, content_type) classmethod","text":"

                                    Create split actions of sub model.

                                    Source code in trestle/core/commands/split.py
                                    @classmethod\ndef prepare_sub_model_split_actions(\n    cls,\n    sub_model_item: OscalBaseModel,\n    sub_model_dir: pathlib.Path,\n    file_prefix: str,\n    content_type: FileContentType\n) -> List[Action]:\n\"\"\"Create split actions of sub model.\"\"\"\n    actions: List[Action] = []\n    file_name = cmd_utils.to_model_file_name(sub_model_item, file_prefix, content_type)\n    model_type = classname_to_alias(type(sub_model_item).__name__, AliasMode.JSON)\n    sub_model_file = sub_model_dir / file_name\n    actions.append(CreatePathAction(sub_model_file))\n    actions.append(WriteFileAction(sub_model_file, Element(sub_model_item, model_type), content_type))\n    return actions\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.split_model","title":"split_model(model_obj, element_paths, base_dir, content_type, root_file_name, aliases_to_strip) classmethod","text":"

                                    Split the model at the provided element paths.

                                    It returns a plan for the operation

                                    Source code in trestle/core/commands/split.py
                                    @classmethod\ndef split_model(\n    cls,\n    model_obj: OscalBaseModel,\n    element_paths: List[ElementPath],\n    base_dir: pathlib.Path,\n    content_type: FileContentType,\n    root_file_name: str,\n    aliases_to_strip: Dict[str, AliasTracker]\n) -> Plan:\n\"\"\"Split the model at the provided element paths.\n\n    It returns a plan for the operation\n    \"\"\"\n    # initialize plan\n    split_plan = Plan()\n\n    # loop through the element path list and update the split_plan\n    stripped_field_alias = []\n    cur_path_index = 0\n    while cur_path_index < len(element_paths):\n        # extract the sub element name for each of the root path of the path chain\n        element_path = element_paths[cur_path_index]\n\n        if element_path.get_parent() is None and len(element_path.get()) > 1:\n            stripped_part = element_path.get()[1]\n            if stripped_part == ElementPath.WILDCARD:\n                stripped_field_alias.append('__root__')\n            else:\n                if stripped_part not in stripped_field_alias:\n                    stripped_field_alias.append(stripped_part)\n\n        # split model at the path chain\n        cur_path_index = cls.split_model_at_path_chain(\n            model_obj,\n            element_paths,\n            base_dir,\n            content_type,\n            cur_path_index,\n            split_plan,\n            False,\n            root_file_name,\n            aliases_to_strip\n        )\n\n        cur_path_index += 1\n\n    # strip the root model object and add a WriteAction\n    stripped_root = model_obj.stripped_instance(stripped_fields_aliases=stripped_field_alias)\n    # If it's an empty model after stripping the fields, don't create path and don't write\n    if set(model_obj.__fields__.keys()) == set(stripped_field_alias):\n        return split_plan\n    if root_file_name != '':\n        root_file = base_dir / root_file_name\n    else:\n        root_file = base_dir / element_paths[0].to_root_path(content_type)\n    split_plan.add_action(CreatePathAction(root_file, True))\n    wrapper_alias = classname_to_alias(stripped_root.__class__.__name__, AliasMode.JSON)\n    split_plan.add_action(WriteFileAction(root_file, Element(stripped_root, wrapper_alias), content_type))\n\n    return split_plan\n
                                    "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.split_model_at_path_chain","title":"split_model_at_path_chain(model_obj, element_paths, base_dir, content_type, cur_path_index, split_plan, strip_root, root_file_name, aliases_to_strip, last_one=True) classmethod","text":"

                                    Recursively split the model at the provided chain of element paths.

                                    It assumes that a chain of element paths starts at the cur_path_index with the first path ending with a wildcard (*)

                                    If the wildcard follows an element that is inherently a list of items, the list of items is extracted. But if the wildcard follows a generic model than members of that model class found in the model will be split off. But only the non-trivial elements are removed, i.e. not str, int, datetime, etc.

                                    Parameters:

                                    Name Type Description Default model_obj OscalBaseModel

                                    The OscalBaseModel to be split

                                    required element_paths List[trestle.core.models.elements.ElementPath]

                                    The List[ElementPath] of elements to split, including embedded wildcards

                                    required base_dir Path

                                    pathlib.Path of the file being split

                                    required content_type FileContentType

                                    json or yaml files

                                    required cur_path_index int

                                    Index into the list of element paths for the current split operation

                                    required split_plan Plan

                                    The accumulated plan of actions needed to perform the split

                                    required strip_root bool

                                    Whether to strip elements from the root object

                                    required root_file_name str

                                    Filename of root file that gets split into a list of items

                                    required aliases_to_strip Dict[str, trestle.core.commands.split.AliasTracker]

                                    AliasTracker previously loaded with aliases that need to be split from each element

                                    required last_one bool

                                    bool indicating last item in array has been split and stripped model can now be written

                                    True

                                    Returns:

                                    Type Description int

                                    int representing the index where the chain of the path ends.

                                    Examples:

                                    For example, element paths could have a list of paths as below for a ComponentDefinition model where the first path is the start of the chain.

                                    For each of the sub model described by the first element path (e.g component-defintion.components.) in the chain, the subsequent paths (e.g component.control-implementations.) will be applied recursively to retrieve the sub-sub models: [ 'component-definition.component.', 'component.control-implementations.' ] for a command like below: trestle split -f component.yaml -e component-definition.components..control-implementations.

                                    Source code in trestle/core/commands/split.py
                                    @classmethod\ndef split_model_at_path_chain(\n    cls,\n    model_obj: OscalBaseModel,\n    element_paths: List[ElementPath],\n    base_dir: pathlib.Path,\n    content_type: FileContentType,\n    cur_path_index: int,\n    split_plan: Plan,\n    strip_root: bool,\n    root_file_name: str,\n    aliases_to_strip: Dict[str, AliasTracker],\n    last_one: bool = True\n) -> int:\n\"\"\"Recursively split the model at the provided chain of element paths.\n\n    It assumes that a chain of element paths starts at the cur_path_index with the first path ending\n    with a wildcard (*)\n\n    If the wildcard follows an element that is inherently a list of items, the list of items is extracted.\n    But if the wildcard follows a generic model than members of that model class found in the model will be\n    split off.  But only the non-trivial elements are removed, i.e. not str, int, datetime, etc.\n\n    Args:\n        model_obj: The OscalBaseModel to be split\n        element_paths: The List[ElementPath] of elements to split, including embedded wildcards\n        base_dir: pathlib.Path of the file being split\n        content_type: json or yaml files\n        cur_path_index: Index into the list of element paths for the current split operation\n        split_plan: The accumulated plan of actions needed to perform the split\n        strip_root: Whether to strip elements from the root object\n        root_file_name: Filename of root file that gets split into a list of items\n        aliases_to_strip: AliasTracker previously loaded with aliases that need to be split from each element\n        last_one: bool indicating last item in array has been split and stripped model can now be written\n\n    Returns:\n        int representing the index where the chain of the path ends.\n\n    Examples:\n        For example, element paths could have a list of paths as below for a `ComponentDefinition` model where\n        the first path is the start of the chain.\n\n        For each of the sub model described by the first element path (e.g component-defintion.components.*) in the\n        chain, the subsequent paths (e.g component.control-implementations.*) will be applied recursively\n        to retrieve the sub-sub models:\n        [\n            'component-definition.component.*',\n            'component.control-implementations.*'\n        ]\n        for a command like below:\n        trestle split -f component.yaml -e component-definition.components.*.control-implementations.*\n    \"\"\"\n    if split_plan is None:\n        raise TrestleError('Split plan must have been initialized')\n\n    if cur_path_index < 0:\n        raise TrestleError('Current index of the chain of paths cannot be less than 0')\n\n    # if there are no more element_paths, return the current plan\n    if cur_path_index >= len(element_paths):\n        return cur_path_index\n\n    # initialize local variables\n    element = Element(model_obj)\n    stripped_field_alias: List[str] = []\n\n    # get the sub_model specified by the element_path of this round\n    element_path = element_paths[cur_path_index]\n\n    # does the next element_path point back at me\n    is_parent = cur_path_index + 1 < len(element_paths) and element_paths[cur_path_index\n                                                                          + 1].get_parent() == element_path\n\n    # root dir name for sub models dir\n    # 00000__group.json will have the root_dir name as 00000__group for sub models of group\n    # catalog.json will have the root_dir name as catalog\n    root_dir = ''\n    if root_file_name != '':\n        root_dir = str(pathlib.Path(root_file_name).with_suffix(''))\n\n    sub_models = element.get_at(element_path, False)  # we call sub_models as in plural, but it can be just one\n\n    # assume cur_path_index is the end of the chain\n    # value of this variable may change during recursive split of the sub-models below\n    path_chain_end = cur_path_index\n\n    # if wildcard is present in the element_path and the next path in the chain has current path as the parent,\n    # Then deal with case of list, or split of arbitrary oscalbasemodel\n    if is_parent and element_path.get_last() is not ElementPath.WILDCARD:\n        # create dir for all sub model items\n        sub_models_dir = base_dir / element_path.to_root_path()\n        sub_model_plan = Plan()\n        path_chain_end = cls.split_model_at_path_chain(\n            sub_models,\n            element_paths,\n            sub_models_dir,\n            content_type,\n            cur_path_index + 1,\n            sub_model_plan,\n            True,\n            '',\n            aliases_to_strip\n        )\n        sub_model_actions = sub_model_plan.get_actions()\n        split_plan.add_actions(sub_model_actions)\n    elif element_path.get_last() == ElementPath.WILDCARD:\n        # extract sub-models into a dict with appropriate prefix\n        sub_model_items: Dict[str, OscalBaseModel] = {}\n        sub_models_dir = base_dir / element_path.to_file_path(root_dir=root_dir)\n        if isinstance(sub_models, list):\n            for i, sub_model_item in enumerate(sub_models):\n                # e.g. `groups/00000_groups/`\n                prefix = str(i).zfill(const.FILE_DIGIT_PREFIX_LENGTH)\n                sub_model_items[prefix] = sub_model_item\n\n        # process list sub model items\n        count = 0\n        for key, sub_model_item in sub_model_items.items():\n            count += 1\n            # recursively split the sub-model if there are more element paths to traverse\n            # e.g. split component.control-implementations.*\n            require_recursive_split = cur_path_index + 1 < len(element_paths) and element_paths[\n                cur_path_index + 1].get_parent() == element_path\n\n            if require_recursive_split:\n                # prepare individual directory for each sub-model\n                sub_root_file_name = cmd_utils.to_model_file_name(sub_model_item, key, content_type)\n                sub_model_plan = Plan()\n\n                last_one: bool = count == len(sub_model_items)\n                path_chain_end = cls.split_model_at_path_chain(\n                    sub_model_item,\n                    element_paths,\n                    sub_models_dir,\n                    content_type,\n                    cur_path_index + 1,\n                    sub_model_plan,\n                    True,\n                    sub_root_file_name,\n                    aliases_to_strip,\n                    last_one\n                )\n                sub_model_actions = sub_model_plan.get_actions()\n            else:\n                sub_model_actions = cls.prepare_sub_model_split_actions(\n                    sub_model_item, sub_models_dir, key, content_type\n                )\n\n            split_plan.add_actions(sub_model_actions)\n    else:\n        # the chain of path ends at the current index.\n        # so no recursive call. Let's just write the sub model to the file and get out\n        if sub_models is not None:\n            sub_model_file = base_dir / element_path.to_file_path(content_type, root_dir=root_dir)\n            split_plan.add_action(CreatePathAction(sub_model_file))\n            split_plan.add_action(\n                WriteFileAction(sub_model_file, Element(sub_models, element_path.get_element_name()), content_type)\n            )\n\n    # Strip the root model and add a WriteAction for the updated model object in the plan\n    if strip_root:\n        full_path = element_path.get_full()\n        path = '.'.join(full_path.split('.')[:-1])\n        aliases = [element_path.get_element_name()]\n        need_to_write = True\n        use_alias_dict = aliases_to_strip is not None and path in aliases_to_strip\n        if use_alias_dict:\n            aliases = aliases_to_strip[path].get_aliases()\n            need_to_write = aliases_to_strip[path].needs_writing()\n\n        stripped_model = model_obj.stripped_instance(stripped_fields_aliases=aliases)\n        # can mark it written even if it doesn't need writing since it is empty\n        # but if an array only mark it written if it's the last one\n        if last_one and use_alias_dict:\n            aliases_to_strip[path].mark_written()\n        # If it's an empty model after stripping the fields, don't create path and don't write\n        field_list = [x for x in model_obj.__fields__.keys() if model_obj.__fields__[x] is not None]\n        if set(field_list) == set(stripped_field_alias):\n            return path_chain_end\n\n        if need_to_write:\n            if root_file_name != '':\n                root_file = base_dir / root_file_name\n            else:\n                root_file = base_dir / element_path.to_root_path(content_type)\n\n            split_plan.add_action(CreatePathAction(root_file))\n            wrapper_alias = classname_to_alias(stripped_model.__class__.__name__, AliasMode.JSON)\n            split_plan.add_action(WriteFileAction(root_file, Element(stripped_model, wrapper_alias), content_type))\n\n    # return the end of the current path chain\n    return path_chain_end\n
                                    "},{"location":"api_reference/trestle.core.commands.task/","title":"task","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task","title":"trestle.core.commands.task","text":"

                                    Trestle task command.

                                    "},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task.TaskCmd","title":" TaskCmd (CommandPlusDocs) ","text":"

                                    Run arbitrary trestle tasks in a simple and extensible methodology.

                                    Source code in trestle/core/commands/task.py
                                    class TaskCmd(CommandPlusDocs):\n\"\"\"Run arbitrary trestle tasks in a simple and extensible methodology.\"\"\"\n\n    name = 'task'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            'task',\n            nargs='?',\n            type=str,\n            help='The name of the task to be run, trestle task -l will list available tasks.'\n        )\n        self.add_argument('-l', '--list', action='store_true', help='List the available tasks')\n        self.add_argument(\n            '-c', '--config', type=pathlib.Path, help='Pass a customized configuration file specifically for a task'\n        )\n        self.add_argument('-i', '--info', action='store_true', help='Print information about a particular task.')\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            logger.debug('Entering trestle task.')\n            log.set_log_level_from_args(args)\n            # Initial logic for conflicting args\n            if args.task and args.list:\n                raise TrestleIncorrectArgsError('Task name or -l can be provided not both.')\n\n            if not args.task and not args.list:\n                raise TrestleIncorrectArgsError(\n                    'Either a trestle task or \"-l/--list\" shoudl be passed as input arguments.'\n                )\n\n            # Ensure trestle directory (must be true)\n            trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n            if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n                raise TrestleError(f'Given directory: {trestle_root} is not a trestle project.')\n\n            config_path = trestle_root / const.TRESTLE_CONFIG_DIR / const.TRESTLE_CONFIG_FILE\n\n            if args.config:\n                config_path = pathlib.Path(args.config)\n            if not config_path.exists():\n                raise TrestleError(f'Config file at {config_path} does not exist.')\n\n            # permit ${name} in config definitions\n            global_config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())\n            global_config.read_file(config_path.open('r', encoding=const.FILE_ENCODING))\n            # run setup\n            task_index = self._build_task_index()\n\n            # Clean to run\n            if args.list:\n                self._list_tasks(task_index)\n                return CmdReturnCodes.SUCCESS.value\n            # run the task\n            if args.task not in task_index.keys():\n                raise TrestleIncorrectArgsError(f'Unknown trestle task: {args.task}')\n\n            logger.debug(f'Loading task: {args.task}')\n            section_label = 'task.' + args.task\n            config_section: Optional[configparser.SectionProxy] = None\n            if section_label in global_config.sections():\n                config_section = global_config[section_label]\n            else:\n                logger.warning(\n                    f'Config file was not configured with the appropriate section for the task: \"[{section_label}]\"'\n                )\n\n            task = task_index[args.task](config_section)\n            if args.info:\n                task.print_info()\n                return CmdReturnCodes.SUCCESS.value\n\n            simulate_result = task.simulate()\n            if not (simulate_result == TaskOutcome.SIM_SUCCESS):\n                raise TrestleError(f'Task {args.task} reported a {simulate_result}')\n\n            actual_result = task.execute()\n            if not (actual_result == TaskOutcome.SUCCESS):\n                raise TrestleError(f'Task {args.task} reported a {actual_result}')\n\n            logger.info(f'Task: {args.task} executed successfully.')\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while executing Trestle task')\n\n    def _build_task_index(self) -> Dict[str, Type[TaskBase]]:\n\"\"\"Build an index of all classes in which are tasks and present as a dictionary.\"\"\"\n        task_index: Dict[str, Type[TaskBase]] = {}\n        pkgpath = str(pathlib.Path(trestle.tasks.__file__).parent)\n        for _, name, _ in pkgutil.iter_modules([pkgpath]):\n            __import__(f'trestle.tasks.{name}')\n            clsmembers = inspect.getmembers(sys.modules[f'trestle.tasks.{name}'], inspect.isclass)\n            for candidate in clsmembers:\n                if issubclass(candidate[1], TaskBase):\n                    task_index[candidate[1].name] = candidate[1]\n        return task_index\n\n    def _list_tasks(self, task_index: Dict[str, Type[TaskBase]]) -> None:\n        logger.info('Available tasks:')\n        for key in task_index.keys():\n            logger.info(f'    {key}')\n
                                    "},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task.TaskCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.validate/","title":"validate","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate","title":"trestle.core.commands.validate","text":"

                                    Trestle Validate Command.

                                    "},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate.ValidateCmd","title":" ValidateCmd (CommandPlusDocs) ","text":"

                                    Validate contents of a trestle model in different modes.

                                    Source code in trestle/core/commands/validate.py
                                    class ValidateCmd(CommandPlusDocs):\n\"\"\"Validate contents of a trestle model in different modes.\"\"\"\n\n    name = ARG_VALIDATE\n\n    def _init_arguments(self) -> None:\n        vfact.init_arguments(self)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n\n            mode_args = argparse.Namespace(mode=VAL_MODE_ALL)\n            validator = vfact.validator_factory.get(mode_args)\n\n            return validator.validate(args)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while validating contents of a trestle model')\n
                                    "},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate.ValidateCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.version/","title":"version","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version","title":"trestle.core.commands.version","text":"

                                    Trestle Validate Command.

                                    "},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version.VersionCmd","title":" VersionCmd (CommandBase) ","text":"

                                    Output version info for trestle and OSCAL.

                                    Source code in trestle/core/commands/version.py
                                    class VersionCmd(CommandBase):\n\"\"\"Output version info for trestle and OSCAL.\"\"\"\n\n    name = 'version'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-n', '--name', help='Name of the OSCAL model', default=None, type=str)\n        self.add_argument(\n            '-t',\n            '--type',\n            help='Type of the model being queried: (catalog, profile, component-definition, ...)',\n            default=None,\n            type=str\n        )\n\n    def _get_version(self, type_name: str, obj_name: str, trestle_root: pathlib.Path) -> str:\n\"\"\"Fetch the version of the OSCAL object from its metadata.\"\"\"\n        oscal_object, obj_path = ModelUtils.load_model_for_type(trestle_root, type_name, obj_name)  # type: ignore\n\n        if not (oscal_object.metadata or oscal_object.metadata.version):  # type: ignore\n            raise TrestleError(f'Unable to determine the version. Metadata version is missing in model: {obj_path}.')\n\n        return oscal_object.metadata.version\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            status = CmdReturnCodes.COMMAND_ERROR.value\n\n            if not args.name and not args.type:\n                version_string = f'Trestle version v{__version__} based on OSCAL version {OSCAL_VERSION}'\n                self.out(version_string)\n                status = CmdReturnCodes.SUCCESS.value\n\n            if not (args.name and args.type) and (args.name or args.type):\n                raise TrestleError('Either both arguments --name and --type should be provided or none.')\n\n            if args.name and args.type:\n                trestle_root = pathlib.Path(args.trestle_root)\n                version = self._get_version(args.type, args.name, trestle_root)\n                version_string = f'Version of OSCAL object of {args.name} {args.type} is: {version}.'\n                self.out(version_string)\n                status = CmdReturnCodes.SUCCESS.value\n\n            return status\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle version')\n
                                    "},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version.VersionCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.control_context/","title":"control_context","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context","title":"trestle.core.control_context","text":"

                                    Provide a context for control operations.

                                    "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose","title":" ContextPurpose (Enum) ","text":"

                                    Specify the modality of the control markdown.

                                    Source code in trestle/core/control_context.py
                                    class ContextPurpose(Enum):\n\"\"\"Specify the modality of the control markdown.\"\"\"\n\n    CATALOG = 0\n    COMPONENT = 1\n    PROFILE = 2\n    SSP = 3\n
                                    "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.CATALOG","title":"CATALOG","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.COMPONENT","title":"COMPONENT","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.PROFILE","title":"PROFILE","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.SSP","title":"SSP","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext","title":" ControlContext dataclass","text":"

                                    Class encapsulating control markdown usage.

                                    Source code in trestle/core/control_context.py
                                    @dataclass\nclass ControlContext:\n\"\"\"Class encapsulating control markdown usage.\"\"\"\n\n    purpose: ContextPurpose\n    to_markdown: bool\n    trestle_root: pathlib.Path\n    md_root: pathlib.Path\n    prompt_responses: bool\n    overwrite_header_values: bool\n    set_parameters_flag: bool\n    cli_yaml_header: Optional[Dict[Any, Any]] = None\n    sections_dict: Optional[Dict[str, str]] = None\n    profile: Optional[prof.Profile] = None\n    required_sections: Optional[List[str]] = None\n    allowed_sections: Optional[List[str]] = None\n    comp_def: Optional[comp.ComponentDefinition] = None\n    comp_name: Optional[str] = None\n    component: Optional[comp.DefinedComponent] = None\n    comp_def_name_list: Optional[List[str]] = None\n    inherited_props: Optional[Dict[str, Any]] = None\n    rules_dict: Optional[Dict[str, Dict[str, Any]]] = None\n    rules_params_dict: Optional[Dict[str, Dict[str, Any]]] = None\n    control_implementation: Optional[comp.ControlImplementation] = None\n    uri_name_map: Optional[Dict[str, str]] = None\n    comp_dict: Optional[CompDict] = None\n    merged_header: Optional[Dict[str, Any]] = None\n\n    @classmethod\n    def generate(\n        cls,\n        purpose: ContextPurpose,\n        to_markdown: bool,\n        trestle_root: pathlib.Path,\n        md_root: pathlib.Path,\n        prompt_responses: bool = False,\n        overwrite_header_values: bool = False,\n        set_parameters_flag: bool = False,\n        cli_yaml_header: Optional[Dict[Any, Any]] = None,\n        sections_dict: Optional[Dict[str, str]] = None,\n        profile: Optional[prof.Profile] = None,\n        required_sections: Optional[List[str]] = None,\n        allowed_sections: Optional[List[str]] = None,\n        comp_def: Optional[comp.ComponentDefinition] = None,\n        comp_name: Optional[str] = None,\n        component: Optional[comp.DefinedComponent] = None,\n        comp_def_name_list: Optional[List[str]] = None,\n        inherited_props: Optional[Dict[str, Any]] = None,\n        rules_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n        rules_params_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n        control_implementation: Optional[comp.ControlImplementation] = None,\n        uri_name_map: Optional[Dict[str, str]] = None,\n        comp_dict: Optional[CompDict] = None,\n        merged_header: Optional[Dict[str, Any]] = None\n    ) -> ControlContext:\n\"\"\"Generate control context of the needed type.\"\"\"\n        context = cls(\n            purpose,\n            to_markdown,\n            trestle_root,\n            md_root,\n            prompt_responses,\n            overwrite_header_values,\n            set_parameters_flag,\n            cli_yaml_header=cli_yaml_header,\n            sections_dict=sections_dict,\n            profile=profile,\n            required_sections=required_sections,\n            allowed_sections=allowed_sections,\n            comp_def=comp_def,\n            comp_name=comp_name,\n            component=component,\n            comp_def_name_list=comp_def_name_list,\n            inherited_props=inherited_props,\n            rules_dict=rules_dict,\n            rules_params_dict=rules_params_dict,\n            control_implementation=control_implementation,\n            uri_name_map=uri_name_map,\n            comp_dict=comp_dict\n        )\n        context.cli_yaml_header = as_dict(cli_yaml_header)\n        context.sections_dict = as_dict(sections_dict)\n        context.merged_header = as_dict(merged_header)\n        # catalog generate always sets params\n        if to_markdown:\n            context.set_parameters = True\n        return context\n\n    @classmethod\n    def clone(cls, context: ControlContext) -> ControlContext:\n\"\"\"Create a deep clone of the context without duplicating large objects.\"\"\"\n        new_context = cls(\n            context.purpose,\n            context.to_markdown,\n            context.trestle_root,\n            context.md_root,\n            context.prompt_responses,\n            context.overwrite_header_values,\n            context.set_parameters_flag,\n            cli_yaml_header=copy.deepcopy(context.cli_yaml_header),\n            sections_dict=copy.deepcopy(context.sections_dict),\n            profile=context.profile,\n            required_sections=context.required_sections,\n            allowed_sections=context.allowed_sections,\n            comp_def=context.comp_def,\n            comp_name=context.comp_name,\n            component=context.component,\n            comp_def_name_list=context.comp_def_name_list,\n            inherited_props=copy.deepcopy(context.inherited_props),\n            rules_dict=copy.deepcopy(context.rules_dict),\n            rules_params_dict=copy.deepcopy(context.rules_params_dict),\n            control_implementation=copy.deepcopy(context.control_implementation),\n            uri_name_map=context.uri_name_map,\n            comp_dict=copy.deepcopy(context.comp_dict),\n            merged_header=copy.deepcopy(context.merged_header)\n        )\n        return new_context\n
                                    "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.allowed_sections","title":"allowed_sections: Optional[List[str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.cli_yaml_header","title":"cli_yaml_header: Optional[Dict[Any, Any]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_def","title":"comp_def: Optional[trestle.oscal.component.ComponentDefinition] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_def_name_list","title":"comp_def_name_list: Optional[List[str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_dict","title":"comp_dict: Optional[Dict[str, Dict[str, trestle.core.control_interface.ComponentImpInfo]]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_name","title":"comp_name: Optional[str] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.component","title":"component: Optional[trestle.oscal.component.DefinedComponent] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.control_implementation","title":"control_implementation: Optional[trestle.oscal.component.ControlImplementation] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.inherited_props","title":"inherited_props: Optional[Dict[str, Any]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.md_root","title":"md_root: Path dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.merged_header","title":"merged_header: Optional[Dict[str, Any]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.overwrite_header_values","title":"overwrite_header_values: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.profile","title":"profile: Optional[trestle.oscal.profile.Profile] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.prompt_responses","title":"prompt_responses: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.purpose","title":"purpose: ContextPurpose dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.required_sections","title":"required_sections: Optional[List[str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.rules_dict","title":"rules_dict: Optional[Dict[str, Dict[str, Any]]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.rules_params_dict","title":"rules_params_dict: Optional[Dict[str, Dict[str, Any]]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.sections_dict","title":"sections_dict: Optional[Dict[str, str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.set_parameters_flag","title":"set_parameters_flag: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.to_markdown","title":"to_markdown: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.trestle_root","title":"trestle_root: Path dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.uri_name_map","title":"uri_name_map: Optional[Dict[str, str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.__init__","title":"__init__(self, purpose, to_markdown, trestle_root, md_root, prompt_responses, overwrite_header_values, set_parameters_flag, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) special","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.clone","title":"clone(context) classmethod","text":"

                                    Create a deep clone of the context without duplicating large objects.

                                    Source code in trestle/core/control_context.py
                                    @classmethod\ndef clone(cls, context: ControlContext) -> ControlContext:\n\"\"\"Create a deep clone of the context without duplicating large objects.\"\"\"\n    new_context = cls(\n        context.purpose,\n        context.to_markdown,\n        context.trestle_root,\n        context.md_root,\n        context.prompt_responses,\n        context.overwrite_header_values,\n        context.set_parameters_flag,\n        cli_yaml_header=copy.deepcopy(context.cli_yaml_header),\n        sections_dict=copy.deepcopy(context.sections_dict),\n        profile=context.profile,\n        required_sections=context.required_sections,\n        allowed_sections=context.allowed_sections,\n        comp_def=context.comp_def,\n        comp_name=context.comp_name,\n        component=context.component,\n        comp_def_name_list=context.comp_def_name_list,\n        inherited_props=copy.deepcopy(context.inherited_props),\n        rules_dict=copy.deepcopy(context.rules_dict),\n        rules_params_dict=copy.deepcopy(context.rules_params_dict),\n        control_implementation=copy.deepcopy(context.control_implementation),\n        uri_name_map=context.uri_name_map,\n        comp_dict=copy.deepcopy(context.comp_dict),\n        merged_header=copy.deepcopy(context.merged_header)\n    )\n    return new_context\n
                                    "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.generate","title":"generate(purpose, to_markdown, trestle_root, md_root, prompt_responses=False, overwrite_header_values=False, set_parameters_flag=False, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) classmethod","text":"

                                    Generate control context of the needed type.

                                    Source code in trestle/core/control_context.py
                                    @classmethod\ndef generate(\n    cls,\n    purpose: ContextPurpose,\n    to_markdown: bool,\n    trestle_root: pathlib.Path,\n    md_root: pathlib.Path,\n    prompt_responses: bool = False,\n    overwrite_header_values: bool = False,\n    set_parameters_flag: bool = False,\n    cli_yaml_header: Optional[Dict[Any, Any]] = None,\n    sections_dict: Optional[Dict[str, str]] = None,\n    profile: Optional[prof.Profile] = None,\n    required_sections: Optional[List[str]] = None,\n    allowed_sections: Optional[List[str]] = None,\n    comp_def: Optional[comp.ComponentDefinition] = None,\n    comp_name: Optional[str] = None,\n    component: Optional[comp.DefinedComponent] = None,\n    comp_def_name_list: Optional[List[str]] = None,\n    inherited_props: Optional[Dict[str, Any]] = None,\n    rules_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n    rules_params_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n    control_implementation: Optional[comp.ControlImplementation] = None,\n    uri_name_map: Optional[Dict[str, str]] = None,\n    comp_dict: Optional[CompDict] = None,\n    merged_header: Optional[Dict[str, Any]] = None\n) -> ControlContext:\n\"\"\"Generate control context of the needed type.\"\"\"\n    context = cls(\n        purpose,\n        to_markdown,\n        trestle_root,\n        md_root,\n        prompt_responses,\n        overwrite_header_values,\n        set_parameters_flag,\n        cli_yaml_header=cli_yaml_header,\n        sections_dict=sections_dict,\n        profile=profile,\n        required_sections=required_sections,\n        allowed_sections=allowed_sections,\n        comp_def=comp_def,\n        comp_name=comp_name,\n        component=component,\n        comp_def_name_list=comp_def_name_list,\n        inherited_props=inherited_props,\n        rules_dict=rules_dict,\n        rules_params_dict=rules_params_dict,\n        control_implementation=control_implementation,\n        uri_name_map=uri_name_map,\n        comp_dict=comp_dict\n    )\n    context.cli_yaml_header = as_dict(cli_yaml_header)\n    context.sections_dict = as_dict(sections_dict)\n    context.merged_header = as_dict(merged_header)\n    # catalog generate always sets params\n    if to_markdown:\n        context.set_parameters = True\n    return context\n
                                    "},{"location":"api_reference/trestle.core.control_interface/","title":"control_interface","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface","title":"trestle.core.control_interface","text":"

                                    Handle queries and utility operations on controls in memory.

                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.CompDict","title":"CompDict","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo","title":" ComponentImpInfo dataclass","text":"

                                    Class to capture component prose and status.

                                    Source code in trestle/core/control_interface.py
                                    @dataclass\nclass ComponentImpInfo:\n\"\"\"Class to capture component prose and status.\"\"\"\n\n    prose: str\n    rules: List[str]\n    props: List[common.Property]\n    # the lambda is needed to prevent a mutable from being used as a default\n    # without the lambda it would break python 3.11 and is a bug either way\n    status: common.ImplementationStatus = field(\n        default_factory=lambda: common.ImplementationStatus(state=const.STATUS_OPERATIONAL)\n    )\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.props","title":"props: List[trestle.oscal.common.Property] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.prose","title":"prose: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.rules","title":"rules: List[str] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.status","title":"status: ImplementationStatus dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.__init__","title":"__init__(self, prose, rules, props, status=<factory>) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface","title":" ControlInterface ","text":"

                                    Class to interact with controls in memory.

                                    Source code in trestle/core/control_interface.py
                                    class ControlInterface:\n\"\"\"Class to interact with controls in memory.\"\"\"\n\n    @staticmethod\n    def _wrap_label(label: str):\n        l_side = '\\['\n        r_side = '\\]'\n        wrapped = '' if label == '' else f'{l_side}{label}{r_side}'\n        return wrapped\n\n    @staticmethod\n    def _gap_join(a_str: str, b_str: str) -> str:\n        a_clean = a_str.strip()\n        b_clean = b_str.strip()\n        if not b_clean:\n            return a_clean\n        gap = '\\n\\n' if a_clean else ''\n        return a_clean + gap + b_clean\n\n    @staticmethod\n    def _get_control_section_part(part: common.Part, section_name: str) -> str:\n\"\"\"Get the prose for a named section in the control.\"\"\"\n        prose = ''\n        if part.name == section_name and part.prose is not None:\n            prose = ControlInterface._gap_join(prose, part.prose)\n        if part.parts:\n            for sub_part in part.parts:\n                prose = ControlInterface._gap_join(\n                    prose, ControlInterface._get_control_section_part(sub_part, section_name)\n                )\n        return prose\n\n    @staticmethod\n    def get_control_section_prose(control: cat.Control, section_name: str) -> str:\n\"\"\"Get the prose for the control section.\"\"\"\n        prose = ''\n        if control.parts:\n            for part in control.parts:\n                prose = ControlInterface._gap_join(\n                    prose, ControlInterface._get_control_section_part(part, section_name)\n                )\n        return prose\n\n    @staticmethod\n    def _find_section_info(part: common.Part, skip_section_list: List[str]) -> Tuple[str, str, str]:\n\"\"\"Find section not in list.\"\"\"\n        if part.prose and part.name not in skip_section_list:\n            return part.id, part.name, part.title\n        if part.parts:\n            for sub_part in part.parts:\n                id_, name, title = ControlInterface._find_section_info(sub_part, skip_section_list)\n                if id_:\n                    return id_, name, title\n        return '', '', ''\n\n    @staticmethod\n    def _find_section(control: cat.Control, skip_section_list: List[str]) -> Tuple[str, str, str]:\n\"\"\"Find next section not in list.\"\"\"\n        if control.parts:\n            for part in control.parts:\n                id_, name, title = ControlInterface._find_section_info(part, skip_section_list)\n                if id_:\n                    return id_, name, title\n        return '', '', ''\n\n    @staticmethod\n    def strip_to_make_ncname(label: str) -> str:\n\"\"\"Strip chars to conform with NCNAME regex.\"\"\"\n        orig_label = label\n        # make sure first char is allowed\n        while label and label[0] not in const.NCNAME_UTF8_FIRST_CHAR_OPTIONS:\n            label = label[1:]\n        new_label = label[:1]\n        # now check remaining chars\n        if len(label) > 1:\n            for ii in range(1, len(label)):\n                if label[ii] in const.NCNAME_UTF8_OTHER_CHAR_OPTIONS:\n                    new_label += label[ii]\n        # do final check to confirm it is NCNAME\n        match = re.search(const.NCNAME_REGEX, new_label)\n        if not match:\n            raise TrestleError(f'Unable to convert label {orig_label} to NCNAME format.')\n        return new_label\n\n    @staticmethod\n    def get_prop(item: TypeWithProps, prop_name: str, default: Optional[str] = None) -> str:\n\"\"\"Get the property with that name or return empty string.\"\"\"\n        for prop in as_list(item.props):\n            if prop.name.strip().lower() == prop_name.strip().lower():\n                return prop.value.strip()\n        return default if default else ''\n\n    @staticmethod\n    def _delete_prop(part_control: TypeWithProps, prop_name: str) -> None:\n\"\"\"Delete property with that name.\"\"\"\n        # assumes at most one instance\n        names = [prop.name for prop in as_list(part_control.props)]\n        if prop_name in names:\n            index = names.index(prop_name)\n            del part_control.props[index]\n        part_control.props = none_if_empty(part_control.props)\n\n    @staticmethod\n    def _replace_prop(part_control: TypeWithProps, new_prop: common.Property) -> None:\n\"\"\"Delete property with that name if present and insert new one.\"\"\"\n        # assumes at most one instance\n        names = [prop.name for prop in as_list(part_control.props)]\n        if new_prop.name in names:\n            index = names.index(new_prop.name)\n            del part_control.props[index]\n        part_control.props = as_list(part_control.props)\n        part_control.props.append(new_prop)\n\n    @staticmethod\n    def _apply_params_format(param_str: Optional[str], params_format: Optional[str]) -> Optional[str]:\n        if param_str is not None and params_format:\n            if params_format.count('.') > 1:\n                raise TrestleError(\n                    f'Additional text {params_format} '\n                    f'for the parameter format cannot contain multiple dots (.)'\n                )\n            param_str = params_format.replace('.', param_str)\n        return param_str\n\n    @staticmethod\n    def create_statement_id(control_id: str, lower: bool = False) -> str:\n\"\"\"Create the control statement id from the control id.\"\"\"\n        id_ = f'{control_id}_smt'\n        return id_.lower() if lower else id_\n\n    @staticmethod\n    def get_statement_id(control: cat.Control) -> str:\n\"\"\"Find the statement id in the control.\"\"\"\n        for part in as_list(control.parts):\n            if part.name == const.STATEMENT:\n                return part.id\n        return ControlInterface.create_statement_id(control.id)\n\n    @staticmethod\n    def get_sort_id(control: cat.Control, allow_none=False) -> Optional[str]:\n\"\"\"Get the sort-id for the control.\"\"\"\n        for prop in as_list(control.props):\n            if prop.name == const.SORT_ID:\n                return prop.value.strip()\n        return None if allow_none else control.id\n\n    @staticmethod\n    def get_label(item: TypeWithProps) -> str:\n\"\"\"Get the label from the props of a part or control.\"\"\"\n        return ControlInterface.get_prop(item, 'label')\n\n    @staticmethod\n    def get_part_by_id(item: TypeWithParts, id_: str) -> Optional[common.Part]:\n\"\"\"Find the part within this item's list of parts that matches id.\"\"\"\n        for part in as_list(item.parts):\n            if part.id == id_:\n                return part\n            deep_part = ControlInterface.get_part_by_id(part, id_)\n            if deep_part:\n                return deep_part\n        return None\n\n    @staticmethod\n    def get_part(part: common.Part, item_type: str, skip_id: Optional[str]) -> List[Union[str, List[str]]]:\n\"\"\"\n        Find parts with the specified item type, within the given part.\n\n        For a part in a control find the parts in it that match the item_type\n        Return list of string formatted labels and associated descriptive prose\n        \"\"\"\n        items = []\n        if part.name in [const.STATEMENT, item_type]:\n            # the options here are to force the label to be the part.id or the part.label\n            # the label may be of the form (a) while the part.id is ac-1_smt.a.1.a\n            # here we choose the latter and extract the final element\n            label = ControlInterface.get_label(part)\n            label = part.id.split('.')[-1] if not label else label\n            wrapped_label = ControlInterface._wrap_label(label)\n            pad = '' if wrapped_label == '' or not part.prose else ' '\n            prose = '' if part.prose is None else part.prose\n            # top level prose has already been written out, if present\n            # use presence of . in id to tell if this is top level prose\n            if part.id != skip_id:\n                if '\\n*' in prose:\n                    # it is multiline prose\n                    sub_items = []\n                    multi_prose = prose.split('\\n*')\n                    items.append(f'{wrapped_label}{pad}{multi_prose[0]}')\n                    multi_prose.remove(multi_prose[0])\n                    for prose in multi_prose:\n                        sub_items.append(f'{prose}')\n                    items.append(sub_items)\n                else:\n                    items.append(f'{wrapped_label}{pad}{prose}')\n            if part.parts:\n                sub_list = []\n                for prt in part.parts:\n                    sub_list.extend(ControlInterface.get_part(prt, item_type, skip_id))\n                sub_list.append('')\n                items.append(sub_list)\n        return items\n\n    @staticmethod\n    def _get_adds_for_control(profile: prof.Profile, control_id: str) -> List[prof.Add]:\n\"\"\"Get the adds for a given control id from a profile.\"\"\"\n        adds: List[prof.Add] = []\n        if profile.modify:\n            for alter in as_list(profile.modify.alters):\n                if alter.control_id == control_id:\n                    adds.extend(as_list(alter.adds))\n        return adds\n\n    @staticmethod\n    def get_all_add_info(control_id: str, profile: prof.Profile) -> List[PartInfo]:\n\"\"\"Get the adds for a control from a profile by control id.\"\"\"\n        part_infos = []\n        for add in ControlInterface._get_adds_for_control(profile, control_id):\n            # add control level props with no name\n            if add.props:\n                smt_part = add.by_id if add.by_id else ''\n                part_infos.append(PartInfo(name='', prose='', smt_part=smt_part, props=add.props))\n            # add part level props with part name\n            for part in as_list(add.parts):\n                subpart_info = ControlInterface._get_part_and_subpart_info(part, add.by_id)\n                part_infos.append(\n                    PartInfo(\n                        name=part.name, prose=part.prose, smt_part=add.by_id, props=part.props, parts=subpart_info\n                    )\n                )\n        return part_infos\n\n    @staticmethod\n    def _get_part_and_subpart_info(part: common.Part, add_by_id: str) -> List[PartInfo]:\n\"\"\"Get part and its subparts info needed for markdown purposes.\"\"\"\n        part_infos = []\n        for subpart in as_list(part.parts):\n            subpart_info = None\n            if subpart.parts:\n                # Recursively add subparts info\n                subpart_info = ControlInterface._get_part_and_subpart_info(subpart, add_by_id)\n            part_infos.append(\n                PartInfo(\n                    name=subpart.name, prose=subpart.prose, smt_part=add_by_id, props=subpart.props, parts=subpart_info\n                )\n            )\n\n        return part_infos\n\n    @staticmethod\n    def get_section(control: cat.Control, skip_section_list: List[str]) -> Tuple[str, str, str, str]:\n\"\"\"Get sections that are not in the list.\"\"\"\n        id_, name, title = ControlInterface._find_section(control, skip_section_list)\n        if id_:\n            return id_, name, title, ControlInterface.get_control_section_prose(control, name)\n        return '', '', '', ''\n\n    @staticmethod\n    def get_part_prose(control: cat.Control, part_name: str) -> str:\n\"\"\"Get the prose for a named part.\"\"\"\n        prose = ''\n        for part in as_list(control.parts):\n            prose += ControlInterface._get_control_section_part(part, part_name)\n        return prose.strip()\n\n    @staticmethod\n    def setparam_to_param(param_id: str, set_param: prof.SetParameter) -> common.Parameter:\n\"\"\"\n        Convert setparameter to parameter.\n\n        Args:\n            param_id: the id of the parameter\n            set_param: the set_parameter from a profile\n\n        Returns:\n            a Parameter with param_id and content from the SetParameter\n        \"\"\"\n        return common.Parameter(\n            id=param_id, values=set_param.values, select=set_param.select, label=set_param.label, props=set_param.props\n        )\n\n    @staticmethod\n    def uniquify_set_params(set_params: Optional[List[TypeWithParamId]]) -> List[TypeWithParamId]:\n\"\"\"Remove items with same param_id with priority to later items.\"\"\"\n        found_ids: Set[str] = set()\n        unique_list: List[TypeWithParamId] = []\n        for set_param in reversed(as_list(set_params)):\n            if set_param.param_id not in found_ids:\n                unique_list.append(set_param)\n                found_ids.add(set_param.param_id)\n        return list(reversed(unique_list))\n\n    @staticmethod\n    def get_rules_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all rules found in this items props.\"\"\"\n        # rules is dict containing rule_id and description\n        rules_dict = {}\n        name = ''\n        desc = ''\n        id_ = ''\n        rules_props = []\n        for prop in as_list(item.props):\n            if prop.name == const.RULE_ID:\n                name = prop.value\n                id_ = prop.remarks\n                rules_props.append(prop)\n            elif prop.name == const.RULE_DESCRIPTION:\n                desc = prop.value\n                rules_props.append(prop)\n            # grab each pair in case there are multiple pairs\n            # then clear and look for new pair\n            if name and desc:\n                rules_dict[id_] = {'name': name, 'description': desc}\n                name = desc = id_ = ''\n        return rules_dict, rules_props\n\n    @staticmethod\n    def item_has_rules(item: TypeWithProps) -> bool:\n\"\"\"Determine if the item has rules in its props.\"\"\"\n        _, rules_props = ControlInterface.get_rules_dict_from_item(item)\n        return bool(rules_props)\n\n    @staticmethod\n    def get_rule_list_for_item(item: TypeWithProps) -> Tuple[List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to this item from its top level props.\"\"\"\n        props = []\n        rule_list = []\n        for prop in as_list(item.props):\n            if prop.name == const.RULE_ID:\n                rule_list.append(prop.value)\n                props.append(prop)\n        return rule_list, props\n\n    @staticmethod\n    def get_rule_list_for_imp_req(\n        imp_req: ossp.ImplementedRequirement\n    ) -> Tuple[List[str], List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to an imp_req as two lists.\"\"\"\n        comp_rules, rule_props = ControlInterface.get_rule_list_for_item(imp_req)\n        statement_rules = set()\n        for statement in as_list(imp_req.statements):\n            stat_rules, statement_props = ControlInterface.get_rule_list_for_item(statement)\n            statement_rules.update(stat_rules)\n            rule_props.extend(statement_props)\n        return comp_rules, sorted(statement_rules), rule_props\n\n    @staticmethod\n    def get_params_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all params found in this item with rule_id as key.\"\"\"\n        # id, description, options - where options is a string containing comma-sep list of items\n        # params is dict with rule_id as key and value contains: param_name, description and choices\n        params: Dict[str, List[Dict[str, str]]] = {}\n        props = []\n        for prop in as_list(item.props):\n            if const.PARAMETER_ID in prop.name:\n                rule_id = prop.remarks\n                param_name = prop.value\n                # rule already exists in parameters dict\n                if rule_id in params.keys():\n                    existing_param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                    if existing_param is not None:\n                        raise TrestleError(f'Param id for rule {rule_id} already exists')\n                    else:\n                        # append a new parameter for the current rule\n                        params[rule_id].append({'name': param_name})\n                else:\n                    # create new param for this rule for the first parameter\n                    params[rule_id] = [{'name': param_name}]\n                props.append(prop)\n            elif const.PARAMETER_DESCRIPTION in prop.name:\n                rule_id = prop.remarks\n                if rule_id in params:\n                    param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                    param['description'] = prop.value\n                    props.append(prop)\n                else:\n                    raise TrestleError(f'Param description for rule {rule_id} found with no param_id')\n            elif const.PARAMETER_VALUE_ALTERNATIVES in prop.name:\n                rule_id = prop.remarks\n                if rule_id in params:\n                    param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                    param['options'] = prop.value\n                    props.append(prop)\n                else:\n                    raise TrestleError(f'Param options for rule {rule_id} found with no param_id')\n        new_params = {}\n        for rule_id, rule_params in params.items():\n            new_params[rule_id] = []\n            for param in rule_params:\n                if 'name' not in param:\n                    logger.warning(f'Parameter for rule_id {rule_id} has no matching name.  Ignoring the param.')\n                else:\n                    param['description'] = param.get('description', '')\n                    param['options'] = param.get('options', '')\n                    new_params[rule_id].append(param)\n        return new_params, props\n\n    @staticmethod\n    def get_rules_and_params_dict_from_item(\n        item: TypeWithProps\n    ) -> Tuple[Dict[str, Dict[str, str]], Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get the rule dict and params dict from item with props.\"\"\"\n        rules_dict, rules_props = ControlInterface.get_rules_dict_from_item(item)\n        params_dict, params_props = ControlInterface.get_params_dict_from_item(item)\n        rules_props.extend(params_props)\n        return rules_dict, params_dict, rules_props\n\n    @staticmethod\n    def get_set_params_from_item(\n        item: Union[comp.ControlImplementation, comp.ImplementedRequirement]\n    ) -> Dict[str, comp.SetParameter]:\n\"\"\"Get set params that have values from control implementation or imp req.\"\"\"\n        return {\n            set_param.param_id: set_param\n            for set_param in as_filtered_list(item.set_parameters, lambda i: i.values)\n        }\n\n    @staticmethod\n    def merge_props(dest: Optional[List[common.Property]],\n                    src: Optional[List[common.Property]]) -> List[common.Property]:\n\"\"\"Merge a source list of properties into a destination list.\"\"\"\n        if not src:\n            return dest\n        new_props: List[common.Property] = []\n        src_map = {prop.name: prop for prop in src}\n        dest_map = {prop.name: prop for prop in dest}\n        all_names = set(src_map.keys()).union(dest_map.keys())\n        for name in sorted(all_names):\n            if name in src_map and name not in dest_map:\n                new_props.append(src_map[name])\n            elif name in dest_map and name not in src_map:\n                new_props.append(dest_map[name])\n            else:\n                new_prop = dest_map[name]\n                src_prop = src_map[name]\n                new_prop.class_ = src_prop.class_ if src_prop.class_ else new_prop.class_\n                new_prop.ns = src_prop.ns if src_prop.ns else new_prop.ns\n                new_prop.remarks = src_prop.remarks if src_prop.remarks else new_prop.remarks\n                new_prop.uuid = src_prop.uuid if src_prop.uuid else new_prop.uuid\n                new_prop.value = src_prop.value\n                new_props.append(new_prop)\n        return new_props\n\n    @staticmethod\n    def merge_part(dest: common.Part, src: common.Part) -> common.Part:\n\"\"\"Merge a source part into the destination part.\"\"\"\n        dest.name = src.name if src.name else dest.name\n        dest.ns = src.ns if src.ns else dest.ns\n        dest.props = none_if_empty(ControlInterface.merge_props(dest.props, src.props))\n        dest.prose = src.prose\n        dest.title = src.title if src.title else dest.title\n        ControlInterface.merge_parts(dest, src)\n        return dest\n\n    @staticmethod\n    def merge_parts(dest: TypeWithParts, src: TypeWithParts) -> None:\n\"\"\"Merge the parts from the source into the destination.\"\"\"\n        if not dest.parts:\n            dest.parts = src.parts\n        elif not src.parts:\n            dest.parts = None\n        else:\n            new_parts: List[common.Part] = []\n            dest_map = {part.id: part for part in dest.parts}\n            for src_part in src.parts:\n                dest_part = dest_map.get(src_part.id, None)\n                if not dest_part:\n                    new_parts.append(src_part)\n                else:\n                    new_part = ControlInterface.merge_part(dest_part, src_part)\n                    if new_part:\n                        new_parts.append(new_part)\n            dest.parts = new_parts\n\n    @staticmethod\n    def merge_dicts_deep(\n        dest: Dict[Any, Any],\n        src: Dict[Any, Any],\n        overwrite_header_values: bool,\n        depth: int = 0,\n        level: int = 0\n    ) -> None:\n\"\"\"\n        Merge dict src into dest.\n\n        New items are always added from src to dest.\n        Items present in both will be overriden dest if overwrite_header_values is True.\n        \"\"\"\n        for key in src.keys():\n            if key in dest:\n                if depth and level == depth:\n                    if overwrite_header_values:\n                        dest[key] = src[key]\n                    continue\n                # if they are both dicts, recurse\n                if isinstance(dest[key], dict) and isinstance(src[key], dict):\n                    ControlInterface.merge_dicts_deep(dest[key], src[key], overwrite_header_values, depth, level + 1)\n                # if they are both lists, add any item that is not already in the list\n                elif isinstance(dest[key], list) and isinstance(src[key], list):\n                    for item in src[key]:\n                        if item not in dest[key]:\n                            dest[key].append(item)\n                # otherwise override dest if needed\n                elif overwrite_header_values:\n                    dest[key] = src[key]\n            else:\n                # if the item was not already in dest, add it from src\n                dest[key] = src[key]\n\n    @staticmethod\n    def is_withdrawn(control: cat.Control) -> bool:\n\"\"\"\n        Determine if control is marked Withdrawn.\n\n        Args:\n            control: The control that may be marked withdrawn.\n\n        Returns:\n            True if marked withdrawn, false otherwise.\n\n        This is determined by property with name 'status' with value 'Withdrawn'.\n        \"\"\"\n        for _ in as_filtered_list(\n                control.props,\n                lambda p: strip_lower_equals(p.name, 'status') and strip_lower_equals(p.value, 'withdrawn')):\n            return True\n        return False\n\n    @staticmethod\n    def _setparam_values_as_str(set_param: comp.SetParameter) -> str:\n\"\"\"Convert values to string.\"\"\"\n        out_str = ''\n        for value in as_list(set_param.values):\n            value_str = string_from_root(value)\n            if value_str:\n                if out_str:\n                    out_str += ', '\n                out_str += value_str\n        return out_str\n\n    @staticmethod\n    def _param_values_as_str_list(param: common.Parameter) -> List[str]:\n\"\"\"Convert param values to list of strings.\"\"\"\n        return as_list(param.values)\n\n    @staticmethod\n    def _param_values_as_str(param: common.Parameter, brackets=False) -> Optional[str]:\n\"\"\"Convert param values to string with optional brackets.\"\"\"\n        if not param.values:\n            return None\n        values_str = ', '.join(ControlInterface._param_values_as_str_list(param))\n        return f'[{values_str}]' if brackets else values_str\n\n    @staticmethod\n    def _param_selection_as_str(param: common.Parameter, verbose: bool = False, brackets: bool = False) -> str:\n\"\"\"Convert parameter selection to str.\"\"\"\n        if param.select and param.select.choice:\n            how_many_str = ''\n            # if all values are specified there is no how_many string and parens are dropped.  See ac-2.2\n            if param.select.how_many:\n                how_many_str = ' (one)' if param.select.how_many == const.ONE else ' (one or more)'\n            choices_str = '; '.join(as_list(param.select.choice))\n            choices_str = f'[{choices_str}]' if brackets else choices_str\n            choices_str = f'Selection{how_many_str}: {choices_str}' if verbose else choices_str\n            return choices_str\n        return ''\n\n    @staticmethod\n    def _param_label_choices_as_str(param: common.Parameter, verbose: bool = False, brackets: bool = False) -> str:\n\"\"\"Convert param label or choices to string, using choices if present.\"\"\"\n        choices = ControlInterface._param_selection_as_str(param, verbose, brackets)\n        text = choices if choices else param.label\n        text = text if text else param.id\n        return text\n\n    @staticmethod\n    def _param_values_assignment_str(\n        param: common.Parameter,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> str:\n\"\"\"Convert param values, label or choices to string.\"\"\"\n        # use values if present\n        param_str = ControlInterface._param_values_as_str(param, False)\n        if param_str and value_assigned_prefix:\n            param_str = f'{value_assigned_prefix} {param_str}'\n        # otherwise use param selection if present\n        if not param_str:\n            param_str = ControlInterface._param_selection_as_str(param, True, False)\n        # finally use label and param_id as fallbacks\n        if not param_str:\n            param_str = param.label if param.label else param.id\n            if value_not_assigned_prefix:\n                param_str = f'{value_not_assigned_prefix} {param_str}'\n        return f'{param_str}'\n\n    @staticmethod\n    def _param_labels_assignment_str(\n        param: common.Parameter,\n        label_prefix: Optional[str] = None,\n    ) -> str:\n\"\"\"Convert param label or choices to string.\"\"\"\n        # use values if present\n        param_str = ControlInterface._param_selection_as_str(param, True, False)\n        # finally use label and param_id as fallbacks\n        if not param_str:\n            param_str = param.label if param.label else param.id\n            if label_prefix:\n                param_str = f'{label_prefix} {param_str}'\n        return f'{param_str}'\n\n    @staticmethod\n    def param_to_str(\n        param: common.Parameter,\n        param_rep: ParameterRep,\n        verbose: bool = False,\n        brackets: bool = False,\n        params_format: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> Optional[str]:\n\"\"\"\n        Convert parameter to string based on best available representation.\n\n        Args:\n            param: the parameter to convert\n            param_rep: how to represent the parameter\n            verbose: provide verbose text for selection choices\n            brackets: add brackets around the lists of items\n            params_format: a string containing a single dot that represents a form of highlighting around the param\n            value_assigned_prefix: string to place before the parameter string if a value was assigned\n            value_not_assigned_prefix: string to place before the parameter string if value not assigned\n\n        Returns:\n            formatted string or None\n        \"\"\"\n        param_str = None\n        if param_rep == ParameterRep.VALUE_OR_STRING_NONE:\n            param_str = ControlInterface._param_values_as_str(param)\n            param_str = param_str if param_str else 'None'\n        elif param_rep == ParameterRep.LABEL_OR_CHOICES:\n            param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n        elif param_rep == ParameterRep.VALUE_OR_LABEL_OR_CHOICES:\n            param_str = ControlInterface._param_values_as_str(param)\n            if not param_str:\n                param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n        elif param_rep == ParameterRep.VALUE_OR_EMPTY_STRING:\n            param_str = ControlInterface._param_values_as_str(param, brackets)\n            if not param_str:\n                param_str = ''\n        elif param_rep == ParameterRep.ASSIGNMENT_FORM:\n            param_str = ControlInterface._param_values_assignment_str(\n                param, value_assigned_prefix, value_not_assigned_prefix\n            )\n            if not param_str:\n                param_str = ''\n        elif param_rep == ParameterRep.LABEL_FORM:\n            param_str = ControlInterface._param_labels_assignment_str(param, value_not_assigned_prefix)\n            if not param_str:\n                param_str = ''\n        return ControlInterface._apply_params_format(param_str, params_format)\n\n    @staticmethod\n    def get_control_param_dict(control: cat.Control, values_only: bool) -> Dict[str, common.Parameter]:\n\"\"\"\n        Create mapping of param id's to params for params in the control.\n\n        Args:\n            control: the control containing params of interest\n            values_only: only add params to the dict that have actual values\n\n        Returns:\n            Dictionary of param_id mapped to param\n\n        Notes:\n            Warning is given if there is a parameter with no ID\n        \"\"\"\n        param_dict: Dict[str, common.Parameter] = {}\n        for param in as_list(control.params):\n            if not param.id:\n                logger.warning(f'Control {control.id} has parameter with no id.  Ignoring.')\n            if param.values or not values_only:\n                param_dict[param.id] = param\n        return param_dict\n\n    @staticmethod\n    def _replace_ids_with_text(\n        prose: str,\n        param_rep: ParameterRep,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> str:\n\"\"\"Find all instances of param_ids in prose and replace each with corresponding parameter representation.\n\n        Need to check all values in dict for a match\n        Reject matches where the string has an adjacent alphanumeric char: param_1 and param_10 or aparam_1\n        \"\"\"\n        for param in param_dict.values():\n            if param.id not in prose:\n                continue\n            # create the replacement text for the param_id\n            param_str = ControlInterface.param_to_str(\n                param, param_rep, False, False, params_format, value_assigned_prefix, value_not_assigned_prefix\n            )\n            # non-capturing groups are odd in re.sub so capture all 3 groups and replace the middle one\n            pattern = r'(^|[^a-zA-Z0-9_])' + param.id + r'($|[^a-zA-Z0-9_])'\n            prose = re.sub(pattern, r'\\1' + param_str + r'\\2', prose)\n        return prose\n\n    @staticmethod\n    def _replace_params(\n        text: str,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> str:\n\"\"\"\n        Replace params found in moustaches with values from the param_dict.\n\n        A single line of prose may contain multiple moustaches.\n        \"\"\"\n        # first check if there are any moustache patterns in the text\n        if param_rep == ParameterRep.LEAVE_MOUSTACHE:\n            return text\n        orig_text = text\n        staches: List[str] = re.findall(r'{{.*?}}', text)\n        if not staches:\n            return text\n        # now have list of all staches including braces, e.g. ['{{foo}}', '{{bar}}']\n        # clean the staches so they just have the param ids\n        param_ids = []\n        for stache in staches:\n            # remove braces so these are just param_ids but may have extra chars\n            stache_contents = stache[2:(-2)]\n            param_id = stache_contents.replace('insert: param,', '').strip()\n            param_ids.append(param_id)\n\n        # now replace original stache text with param values\n        for i, _ in enumerate(staches):\n            # A moustache may refer to a param_id not listed in the control's params\n            if param_ids[i] not in param_dict:\n                if show_value_warnings:\n                    logger.warning(f'Control prose references param {param_ids[i]} not set in the control: {staches}')\n            elif param_dict[param_ids[i]] is not None:\n                param = param_dict[param_ids[i]]\n                param_str = ControlInterface.param_to_str(\n                    param, param_rep, False, False, params_format, value_assigned_prefix, value_not_assigned_prefix\n                )\n                text = text.replace(staches[i], param_str, 1).strip()\n                if show_value_warnings and param_rep != ParameterRep.LABEL_OR_CHOICES and not param.values:\n                    logger.warning(f'Parameter {param_id} has no values and was referenced by prose.')\n            elif show_value_warnings:\n                logger.warning(f'Control prose references param {param_ids[i]} with no specified value.')\n        # there may be staches remaining that we can't replace if not in param_dict\n        if text != orig_text:\n            while True:\n                new_text = ControlInterface._replace_params(\n                    text,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n                if new_text == text:\n                    break\n                text = new_text\n        return text\n\n    @staticmethod\n    def _replace_part_prose(\n        control: cat.Control,\n        part: common.Part,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Replace the part prose according to set_param.\"\"\"\n        if part.prose is not None:\n            fixed_prose = ControlInterface._replace_params(\n                part.prose,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n            # change the prose in the control itself\n            part.prose = fixed_prose\n        for prt in as_list(part.parts):\n            ControlInterface._replace_part_prose(\n                control,\n                prt,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n        for sub_control in as_list(control.controls):\n            for prt in as_list(sub_control.parts):\n                ControlInterface._replace_part_prose(\n                    sub_control,\n                    prt,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n\n    @staticmethod\n    def _replace_param_choices(\n        param: common.Parameter,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str],\n        param_rep: ParameterRep,\n        show_value_warnings: bool,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Set values for all choices param that refer to params with values.\"\"\"\n        if param.select:\n            new_choices: List[str] = []\n            for choice in as_list(param.select.choice):\n                new_choice = ControlInterface._replace_params(\n                    choice,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n                new_choices.append(new_choice)\n            param.select.choice = new_choices\n\n    @staticmethod\n    def replace_control_prose(\n        control: cat.Control,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Replace the control prose according to set_param.\"\"\"\n        # first replace all choices that reference parameters\n        # note that in ASSIGNMENT_FORM each choice with a parameter will end up as [Assignment: value]\n        for param in as_list(control.params):\n            ControlInterface._replace_param_choices(\n                param,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n        for part in as_list(control.parts):\n            if part.prose is not None:\n                fixed_prose = ControlInterface._replace_params(\n                    part.prose,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n                # change the prose in the control itself\n                part.prose = fixed_prose\n            for prt in as_list(part.parts):\n                ControlInterface._replace_part_prose(\n                    control,\n                    prt,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n\n    @staticmethod\n    def bad_header(header: str) -> bool:\n\"\"\"Return true if header format is bad.\"\"\"\n        if not header or header[0] != '#':\n            return True\n        n = len(header)\n        if n < 2:\n            return True\n        for ii in range(1, n):\n            if header[ii] == ' ':\n                return False\n            if header[ii] != '#':\n                return True\n        return True\n\n    @staticmethod\n    def get_component_by_name(comp_def: comp.ComponentDefinition, comp_name: str) -> Optional[comp.DefinedComponent]:\n\"\"\"Get the component with this name from the comp_def.\"\"\"\n        for sub_comp in as_list(comp_def.components):\n            if sub_comp.title == comp_name:\n                return sub_comp\n        return None\n\n    @staticmethod\n    def get_status_from_props(item: TypeWithProps) -> common.ImplementationStatus:\n\"\"\"Get the status of an item from its props.\"\"\"\n        status = common.ImplementationStatus(state=const.STATUS_PLANNED)\n        for prop in as_list(item.props):\n            if prop.name == const.IMPLEMENTATION_STATUS:\n                status = ControlInterface._prop_as_status(prop)\n                break\n        return status\n\n    @staticmethod\n    def clean_props(\n        props: Optional[List[common.Property]],\n        remove_imp_status: bool = True,\n        remove_all_rule_info: bool = False\n    ) -> List[common.Property]:\n\"\"\"Remove duplicate props and implementation status.\"\"\"\n        new_props: List[common.Property] = []\n        found_props: Set[Tuple[str, str, str, str]] = set()\n        rule_tag_list = [\n            const.RULE_DESCRIPTION, const.RULE_ID, const.PARAMETER_DESCRIPTION, const.PARAMETER_VALUE_ALTERNATIVES\n        ]\n        # reverse the list so the latest items are kept\n        for prop in reversed(as_list(props)):\n            prop_tuple = (prop.name, as_string(prop.value), as_string(prop.ns), prop.remarks)\n            if prop_tuple in found_props or (prop.name == const.IMPLEMENTATION_STATUS and remove_imp_status):\n                continue\n            if remove_all_rule_info and prop.name in rule_tag_list:\n                continue\n            found_props.add(prop_tuple)\n            new_props.append(prop)\n        new_props.reverse()\n        return new_props\n\n    @staticmethod\n    def cull_props_by_rules(props: Optional[List[common.Property]], rules: List[str]) -> List[common.Property]:\n\"\"\"Cull properties to the ones needed by rules.\"\"\"\n        needed_rule_ids: Set[str] = set()\n        culled_props: List[common.Property] = []\n        for prop in as_list(props):\n            if prop.value in rules and prop.remarks:\n                needed_rule_ids.add(prop.remarks)\n        for prop in as_list(props):\n            if prop.value in rules or prop.remarks in needed_rule_ids:\n                culled_props.append(prop)\n        return culled_props\n\n    @staticmethod\n    def _status_as_prop(status: common.ImplementationStatus) -> common.Property:\n\"\"\"Convert status to property.\"\"\"\n        return common.Property(name=const.IMPLEMENTATION_STATUS, value=status.state, remarks=status.remarks)\n\n    @staticmethod\n    def _prop_as_status(prop: common.Property) -> common.ImplementationStatus:\n\"\"\"Convert property to status.\"\"\"\n        return common.ImplementationStatus(state=prop.value, remarks=prop.remarks)\n\n    @staticmethod\n    def insert_status_in_props(item: TypeWithProps, status: common.ImplementationStatus) -> None:\n\"\"\"Insert status content into props of the item.\"\"\"\n        prop = ControlInterface._status_as_prop(status)\n        ControlInterface._replace_prop(item, prop)\n\n    @staticmethod\n    def _copy_status_in_props(dest: TypeWithProps, src: TypeWithProps) -> None:\n\"\"\"Copy status in props from one object to another.\"\"\"\n        status = ControlInterface.get_status_from_props(src)\n        ControlInterface.insert_status_in_props(dest, status)\n\n    @staticmethod\n    def insert_imp_req_into_component(\n        component: comp.DefinedComponent,\n        new_imp_req: comp.ImplementedRequirement,\n        profile_title: str,\n        trestle_root: pathlib.Path\n    ) -> None:\n\"\"\"\n        Insert imp req into component by matching source title and control id to existing imp req.\n\n        Args:\n            component: The defined component receiving the imp_req\n            new_imp_req: The new imp_req being added\n            profile_title: The title of the source profile for the control implementation containing the imp_req\n\n        Notes:\n            Inserts the imp_req on the first match found.  Note it is possible two control implementations could\n            have the same source and specify the same control\n        \"\"\"\n        for control_imp in as_list(component.control_implementations):\n            _, control_imp_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)\n            control_imp_rule_param_ids = [\n                param['name'] for params in control_imp_param_dict.values() for param in params\n            ]\n            if profile_title != ModelUtils.get_title_from_model_uri(trestle_root, control_imp.source):\n                continue\n            for imp_req in as_list(control_imp.implemented_requirements):\n                if imp_req.control_id != new_imp_req.control_id:\n                    continue\n                _, imp_req_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(imp_req)\n                imp_req_rule_param_ids = [param['name'] for params in imp_req_param_dict.values() for param in params]\n                status = ControlInterface.get_status_from_props(new_imp_req)\n                ControlInterface.insert_status_in_props(imp_req, status)\n                imp_req.description = new_imp_req.description\n                statement_dict = {stat.statement_id: stat for stat in as_list(imp_req.statements)}\n                # update set parameter values with values from markdown - but only for rule param vals\n                for set_param in as_list(new_imp_req.set_parameters):\n                    if set_param.param_id not in (control_imp_rule_param_ids + imp_req_rule_param_ids):\n                        continue\n                    found = False\n                    for dest_param in as_list(imp_req.set_parameters):\n                        if dest_param.param_id != set_param.param_id:\n                            continue\n                        dest_param.values = set_param.values\n                        found = True\n                        break\n                    # if rule parameter val was not already set by a set_param, make new set_param for it\n                    if found:\n                        continue\n                    # but first check if the parameter was already set with the same value in the control_imp\n                    # if so we don't need to insert a new set_param in imp_req\n                    for dest_param in as_list(control_imp.set_parameters):\n                        if dest_param.param_id != set_param.param_id:\n                            continue\n                        if dest_param.values == set_param.values:\n                            found = True\n                            break\n                    if found:\n                        continue\n                    imp_req.set_parameters = as_list(imp_req.set_parameters)\n                    imp_req.set_parameters.append(\n                        comp.SetParameter(param_id=set_param.param_id, values=set_param.values)\n                    )\n                new_statements: List[comp.Statement] = []\n                for statement in as_list(new_imp_req.statements):\n                    # get the original version of the statement if available, or use new one\n                    stat = statement_dict.get(statement.statement_id, statement)\n                    # update the description and status from markdown\n                    stat.description = statement.description\n                    ControlInterface._copy_status_in_props(stat, statement)\n                    new_statements.append(stat)\n                imp_req.statements = none_if_empty(new_statements)\n                return\n        logger.warning(\n            f'Unable to add imp req for component {component.title} control {new_imp_req.control_id} and source: {profile_title}'  # noqa E501\n        )\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.bad_header","title":"bad_header(header) staticmethod","text":"

                                    Return true if header format is bad.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef bad_header(header: str) -> bool:\n\"\"\"Return true if header format is bad.\"\"\"\n    if not header or header[0] != '#':\n        return True\n    n = len(header)\n    if n < 2:\n        return True\n    for ii in range(1, n):\n        if header[ii] == ' ':\n            return False\n        if header[ii] != '#':\n            return True\n    return True\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.clean_props","title":"clean_props(props, remove_imp_status=True, remove_all_rule_info=False) staticmethod","text":"

                                    Remove duplicate props and implementation status.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef clean_props(\n    props: Optional[List[common.Property]],\n    remove_imp_status: bool = True,\n    remove_all_rule_info: bool = False\n) -> List[common.Property]:\n\"\"\"Remove duplicate props and implementation status.\"\"\"\n    new_props: List[common.Property] = []\n    found_props: Set[Tuple[str, str, str, str]] = set()\n    rule_tag_list = [\n        const.RULE_DESCRIPTION, const.RULE_ID, const.PARAMETER_DESCRIPTION, const.PARAMETER_VALUE_ALTERNATIVES\n    ]\n    # reverse the list so the latest items are kept\n    for prop in reversed(as_list(props)):\n        prop_tuple = (prop.name, as_string(prop.value), as_string(prop.ns), prop.remarks)\n        if prop_tuple in found_props or (prop.name == const.IMPLEMENTATION_STATUS and remove_imp_status):\n            continue\n        if remove_all_rule_info and prop.name in rule_tag_list:\n            continue\n        found_props.add(prop_tuple)\n        new_props.append(prop)\n    new_props.reverse()\n    return new_props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.create_statement_id","title":"create_statement_id(control_id, lower=False) staticmethod","text":"

                                    Create the control statement id from the control id.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef create_statement_id(control_id: str, lower: bool = False) -> str:\n\"\"\"Create the control statement id from the control id.\"\"\"\n    id_ = f'{control_id}_smt'\n    return id_.lower() if lower else id_\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.cull_props_by_rules","title":"cull_props_by_rules(props, rules) staticmethod","text":"

                                    Cull properties to the ones needed by rules.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef cull_props_by_rules(props: Optional[List[common.Property]], rules: List[str]) -> List[common.Property]:\n\"\"\"Cull properties to the ones needed by rules.\"\"\"\n    needed_rule_ids: Set[str] = set()\n    culled_props: List[common.Property] = []\n    for prop in as_list(props):\n        if prop.value in rules and prop.remarks:\n            needed_rule_ids.add(prop.remarks)\n    for prop in as_list(props):\n        if prop.value in rules or prop.remarks in needed_rule_ids:\n            culled_props.append(prop)\n    return culled_props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_all_add_info","title":"get_all_add_info(control_id, profile) staticmethod","text":"

                                    Get the adds for a control from a profile by control id.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_all_add_info(control_id: str, profile: prof.Profile) -> List[PartInfo]:\n\"\"\"Get the adds for a control from a profile by control id.\"\"\"\n    part_infos = []\n    for add in ControlInterface._get_adds_for_control(profile, control_id):\n        # add control level props with no name\n        if add.props:\n            smt_part = add.by_id if add.by_id else ''\n            part_infos.append(PartInfo(name='', prose='', smt_part=smt_part, props=add.props))\n        # add part level props with part name\n        for part in as_list(add.parts):\n            subpart_info = ControlInterface._get_part_and_subpart_info(part, add.by_id)\n            part_infos.append(\n                PartInfo(\n                    name=part.name, prose=part.prose, smt_part=add.by_id, props=part.props, parts=subpart_info\n                )\n            )\n    return part_infos\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_component_by_name","title":"get_component_by_name(comp_def, comp_name) staticmethod","text":"

                                    Get the component with this name from the comp_def.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_component_by_name(comp_def: comp.ComponentDefinition, comp_name: str) -> Optional[comp.DefinedComponent]:\n\"\"\"Get the component with this name from the comp_def.\"\"\"\n    for sub_comp in as_list(comp_def.components):\n        if sub_comp.title == comp_name:\n            return sub_comp\n    return None\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_control_param_dict","title":"get_control_param_dict(control, values_only) staticmethod","text":"

                                    Create mapping of param id's to params for params in the control.

                                    Parameters:

                                    Name Type Description Default control cat.Control

                                    the control containing params of interest

                                    required values_only bool

                                    only add params to the dict that have actual values

                                    required

                                    Returns:

                                    Type Description Dict[str, common.Parameter]

                                    Dictionary of param_id mapped to param

                                    Notes

                                    Warning is given if there is a parameter with no ID

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_control_param_dict(control: cat.Control, values_only: bool) -> Dict[str, common.Parameter]:\n\"\"\"\n    Create mapping of param id's to params for params in the control.\n\n    Args:\n        control: the control containing params of interest\n        values_only: only add params to the dict that have actual values\n\n    Returns:\n        Dictionary of param_id mapped to param\n\n    Notes:\n        Warning is given if there is a parameter with no ID\n    \"\"\"\n    param_dict: Dict[str, common.Parameter] = {}\n    for param in as_list(control.params):\n        if not param.id:\n            logger.warning(f'Control {control.id} has parameter with no id.  Ignoring.')\n        if param.values or not values_only:\n            param_dict[param.id] = param\n    return param_dict\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_control_section_prose","title":"get_control_section_prose(control, section_name) staticmethod","text":"

                                    Get the prose for the control section.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_control_section_prose(control: cat.Control, section_name: str) -> str:\n\"\"\"Get the prose for the control section.\"\"\"\n    prose = ''\n    if control.parts:\n        for part in control.parts:\n            prose = ControlInterface._gap_join(\n                prose, ControlInterface._get_control_section_part(part, section_name)\n            )\n    return prose\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_label","title":"get_label(item) staticmethod","text":"

                                    Get the label from the props of a part or control.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_label(item: TypeWithProps) -> str:\n\"\"\"Get the label from the props of a part or control.\"\"\"\n    return ControlInterface.get_prop(item, 'label')\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_params_dict_from_item","title":"get_params_dict_from_item(item) staticmethod","text":"

                                    Get all params found in this item with rule_id as key.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_params_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all params found in this item with rule_id as key.\"\"\"\n    # id, description, options - where options is a string containing comma-sep list of items\n    # params is dict with rule_id as key and value contains: param_name, description and choices\n    params: Dict[str, List[Dict[str, str]]] = {}\n    props = []\n    for prop in as_list(item.props):\n        if const.PARAMETER_ID in prop.name:\n            rule_id = prop.remarks\n            param_name = prop.value\n            # rule already exists in parameters dict\n            if rule_id in params.keys():\n                existing_param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                if existing_param is not None:\n                    raise TrestleError(f'Param id for rule {rule_id} already exists')\n                else:\n                    # append a new parameter for the current rule\n                    params[rule_id].append({'name': param_name})\n            else:\n                # create new param for this rule for the first parameter\n                params[rule_id] = [{'name': param_name}]\n            props.append(prop)\n        elif const.PARAMETER_DESCRIPTION in prop.name:\n            rule_id = prop.remarks\n            if rule_id in params:\n                param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                param['description'] = prop.value\n                props.append(prop)\n            else:\n                raise TrestleError(f'Param description for rule {rule_id} found with no param_id')\n        elif const.PARAMETER_VALUE_ALTERNATIVES in prop.name:\n            rule_id = prop.remarks\n            if rule_id in params:\n                param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                param['options'] = prop.value\n                props.append(prop)\n            else:\n                raise TrestleError(f'Param options for rule {rule_id} found with no param_id')\n    new_params = {}\n    for rule_id, rule_params in params.items():\n        new_params[rule_id] = []\n        for param in rule_params:\n            if 'name' not in param:\n                logger.warning(f'Parameter for rule_id {rule_id} has no matching name.  Ignoring the param.')\n            else:\n                param['description'] = param.get('description', '')\n                param['options'] = param.get('options', '')\n                new_params[rule_id].append(param)\n    return new_params, props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_part","title":"get_part(part, item_type, skip_id) staticmethod","text":"

                                    Find parts with the specified item type, within the given part.

                                    For a part in a control find the parts in it that match the item_type Return list of string formatted labels and associated descriptive prose

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_part(part: common.Part, item_type: str, skip_id: Optional[str]) -> List[Union[str, List[str]]]:\n\"\"\"\n    Find parts with the specified item type, within the given part.\n\n    For a part in a control find the parts in it that match the item_type\n    Return list of string formatted labels and associated descriptive prose\n    \"\"\"\n    items = []\n    if part.name in [const.STATEMENT, item_type]:\n        # the options here are to force the label to be the part.id or the part.label\n        # the label may be of the form (a) while the part.id is ac-1_smt.a.1.a\n        # here we choose the latter and extract the final element\n        label = ControlInterface.get_label(part)\n        label = part.id.split('.')[-1] if not label else label\n        wrapped_label = ControlInterface._wrap_label(label)\n        pad = '' if wrapped_label == '' or not part.prose else ' '\n        prose = '' if part.prose is None else part.prose\n        # top level prose has already been written out, if present\n        # use presence of . in id to tell if this is top level prose\n        if part.id != skip_id:\n            if '\\n*' in prose:\n                # it is multiline prose\n                sub_items = []\n                multi_prose = prose.split('\\n*')\n                items.append(f'{wrapped_label}{pad}{multi_prose[0]}')\n                multi_prose.remove(multi_prose[0])\n                for prose in multi_prose:\n                    sub_items.append(f'{prose}')\n                items.append(sub_items)\n            else:\n                items.append(f'{wrapped_label}{pad}{prose}')\n        if part.parts:\n            sub_list = []\n            for prt in part.parts:\n                sub_list.extend(ControlInterface.get_part(prt, item_type, skip_id))\n            sub_list.append('')\n            items.append(sub_list)\n    return items\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_part_by_id","title":"get_part_by_id(item, id_) staticmethod","text":"

                                    Find the part within this item's list of parts that matches id.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_part_by_id(item: TypeWithParts, id_: str) -> Optional[common.Part]:\n\"\"\"Find the part within this item's list of parts that matches id.\"\"\"\n    for part in as_list(item.parts):\n        if part.id == id_:\n            return part\n        deep_part = ControlInterface.get_part_by_id(part, id_)\n        if deep_part:\n            return deep_part\n    return None\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_part_prose","title":"get_part_prose(control, part_name) staticmethod","text":"

                                    Get the prose for a named part.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_part_prose(control: cat.Control, part_name: str) -> str:\n\"\"\"Get the prose for a named part.\"\"\"\n    prose = ''\n    for part in as_list(control.parts):\n        prose += ControlInterface._get_control_section_part(part, part_name)\n    return prose.strip()\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_prop","title":"get_prop(item, prop_name, default=None) staticmethod","text":"

                                    Get the property with that name or return empty string.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_prop(item: TypeWithProps, prop_name: str, default: Optional[str] = None) -> str:\n\"\"\"Get the property with that name or return empty string.\"\"\"\n    for prop in as_list(item.props):\n        if prop.name.strip().lower() == prop_name.strip().lower():\n            return prop.value.strip()\n    return default if default else ''\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rule_list_for_imp_req","title":"get_rule_list_for_imp_req(imp_req) staticmethod","text":"

                                    Get the list of rules applying to an imp_req as two lists.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_rule_list_for_imp_req(\n    imp_req: ossp.ImplementedRequirement\n) -> Tuple[List[str], List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to an imp_req as two lists.\"\"\"\n    comp_rules, rule_props = ControlInterface.get_rule_list_for_item(imp_req)\n    statement_rules = set()\n    for statement in as_list(imp_req.statements):\n        stat_rules, statement_props = ControlInterface.get_rule_list_for_item(statement)\n        statement_rules.update(stat_rules)\n        rule_props.extend(statement_props)\n    return comp_rules, sorted(statement_rules), rule_props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rule_list_for_item","title":"get_rule_list_for_item(item) staticmethod","text":"

                                    Get the list of rules applying to this item from its top level props.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_rule_list_for_item(item: TypeWithProps) -> Tuple[List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to this item from its top level props.\"\"\"\n    props = []\n    rule_list = []\n    for prop in as_list(item.props):\n        if prop.name == const.RULE_ID:\n            rule_list.append(prop.value)\n            props.append(prop)\n    return rule_list, props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rules_and_params_dict_from_item","title":"get_rules_and_params_dict_from_item(item) staticmethod","text":"

                                    Get the rule dict and params dict from item with props.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_rules_and_params_dict_from_item(\n    item: TypeWithProps\n) -> Tuple[Dict[str, Dict[str, str]], Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get the rule dict and params dict from item with props.\"\"\"\n    rules_dict, rules_props = ControlInterface.get_rules_dict_from_item(item)\n    params_dict, params_props = ControlInterface.get_params_dict_from_item(item)\n    rules_props.extend(params_props)\n    return rules_dict, params_dict, rules_props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rules_dict_from_item","title":"get_rules_dict_from_item(item) staticmethod","text":"

                                    Get all rules found in this items props.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_rules_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all rules found in this items props.\"\"\"\n    # rules is dict containing rule_id and description\n    rules_dict = {}\n    name = ''\n    desc = ''\n    id_ = ''\n    rules_props = []\n    for prop in as_list(item.props):\n        if prop.name == const.RULE_ID:\n            name = prop.value\n            id_ = prop.remarks\n            rules_props.append(prop)\n        elif prop.name == const.RULE_DESCRIPTION:\n            desc = prop.value\n            rules_props.append(prop)\n        # grab each pair in case there are multiple pairs\n        # then clear and look for new pair\n        if name and desc:\n            rules_dict[id_] = {'name': name, 'description': desc}\n            name = desc = id_ = ''\n    return rules_dict, rules_props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_section","title":"get_section(control, skip_section_list) staticmethod","text":"

                                    Get sections that are not in the list.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_section(control: cat.Control, skip_section_list: List[str]) -> Tuple[str, str, str, str]:\n\"\"\"Get sections that are not in the list.\"\"\"\n    id_, name, title = ControlInterface._find_section(control, skip_section_list)\n    if id_:\n        return id_, name, title, ControlInterface.get_control_section_prose(control, name)\n    return '', '', '', ''\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_set_params_from_item","title":"get_set_params_from_item(item) staticmethod","text":"

                                    Get set params that have values from control implementation or imp req.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_set_params_from_item(\n    item: Union[comp.ControlImplementation, comp.ImplementedRequirement]\n) -> Dict[str, comp.SetParameter]:\n\"\"\"Get set params that have values from control implementation or imp req.\"\"\"\n    return {\n        set_param.param_id: set_param\n        for set_param in as_filtered_list(item.set_parameters, lambda i: i.values)\n    }\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_sort_id","title":"get_sort_id(control, allow_none=False) staticmethod","text":"

                                    Get the sort-id for the control.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_sort_id(control: cat.Control, allow_none=False) -> Optional[str]:\n\"\"\"Get the sort-id for the control.\"\"\"\n    for prop in as_list(control.props):\n        if prop.name == const.SORT_ID:\n            return prop.value.strip()\n    return None if allow_none else control.id\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_statement_id","title":"get_statement_id(control) staticmethod","text":"

                                    Find the statement id in the control.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_statement_id(control: cat.Control) -> str:\n\"\"\"Find the statement id in the control.\"\"\"\n    for part in as_list(control.parts):\n        if part.name == const.STATEMENT:\n            return part.id\n    return ControlInterface.create_statement_id(control.id)\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_status_from_props","title":"get_status_from_props(item) staticmethod","text":"

                                    Get the status of an item from its props.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef get_status_from_props(item: TypeWithProps) -> common.ImplementationStatus:\n\"\"\"Get the status of an item from its props.\"\"\"\n    status = common.ImplementationStatus(state=const.STATUS_PLANNED)\n    for prop in as_list(item.props):\n        if prop.name == const.IMPLEMENTATION_STATUS:\n            status = ControlInterface._prop_as_status(prop)\n            break\n    return status\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.insert_imp_req_into_component","title":"insert_imp_req_into_component(component, new_imp_req, profile_title, trestle_root) staticmethod","text":"

                                    Insert imp req into component by matching source title and control id to existing imp req.

                                    Parameters:

                                    Name Type Description Default component comp.DefinedComponent

                                    The defined component receiving the imp_req

                                    required new_imp_req comp.ImplementedRequirement

                                    The new imp_req being added

                                    required profile_title str

                                    The title of the source profile for the control implementation containing the imp_req

                                    required

                                    Notes

                                    Inserts the imp_req on the first match found. Note it is possible two control implementations could have the same source and specify the same control

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef insert_imp_req_into_component(\n    component: comp.DefinedComponent,\n    new_imp_req: comp.ImplementedRequirement,\n    profile_title: str,\n    trestle_root: pathlib.Path\n) -> None:\n\"\"\"\n    Insert imp req into component by matching source title and control id to existing imp req.\n\n    Args:\n        component: The defined component receiving the imp_req\n        new_imp_req: The new imp_req being added\n        profile_title: The title of the source profile for the control implementation containing the imp_req\n\n    Notes:\n        Inserts the imp_req on the first match found.  Note it is possible two control implementations could\n        have the same source and specify the same control\n    \"\"\"\n    for control_imp in as_list(component.control_implementations):\n        _, control_imp_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)\n        control_imp_rule_param_ids = [\n            param['name'] for params in control_imp_param_dict.values() for param in params\n        ]\n        if profile_title != ModelUtils.get_title_from_model_uri(trestle_root, control_imp.source):\n            continue\n        for imp_req in as_list(control_imp.implemented_requirements):\n            if imp_req.control_id != new_imp_req.control_id:\n                continue\n            _, imp_req_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(imp_req)\n            imp_req_rule_param_ids = [param['name'] for params in imp_req_param_dict.values() for param in params]\n            status = ControlInterface.get_status_from_props(new_imp_req)\n            ControlInterface.insert_status_in_props(imp_req, status)\n            imp_req.description = new_imp_req.description\n            statement_dict = {stat.statement_id: stat for stat in as_list(imp_req.statements)}\n            # update set parameter values with values from markdown - but only for rule param vals\n            for set_param in as_list(new_imp_req.set_parameters):\n                if set_param.param_id not in (control_imp_rule_param_ids + imp_req_rule_param_ids):\n                    continue\n                found = False\n                for dest_param in as_list(imp_req.set_parameters):\n                    if dest_param.param_id != set_param.param_id:\n                        continue\n                    dest_param.values = set_param.values\n                    found = True\n                    break\n                # if rule parameter val was not already set by a set_param, make new set_param for it\n                if found:\n                    continue\n                # but first check if the parameter was already set with the same value in the control_imp\n                # if so we don't need to insert a new set_param in imp_req\n                for dest_param in as_list(control_imp.set_parameters):\n                    if dest_param.param_id != set_param.param_id:\n                        continue\n                    if dest_param.values == set_param.values:\n                        found = True\n                        break\n                if found:\n                    continue\n                imp_req.set_parameters = as_list(imp_req.set_parameters)\n                imp_req.set_parameters.append(\n                    comp.SetParameter(param_id=set_param.param_id, values=set_param.values)\n                )\n            new_statements: List[comp.Statement] = []\n            for statement in as_list(new_imp_req.statements):\n                # get the original version of the statement if available, or use new one\n                stat = statement_dict.get(statement.statement_id, statement)\n                # update the description and status from markdown\n                stat.description = statement.description\n                ControlInterface._copy_status_in_props(stat, statement)\n                new_statements.append(stat)\n            imp_req.statements = none_if_empty(new_statements)\n            return\n    logger.warning(\n        f'Unable to add imp req for component {component.title} control {new_imp_req.control_id} and source: {profile_title}'  # noqa E501\n    )\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.insert_status_in_props","title":"insert_status_in_props(item, status) staticmethod","text":"

                                    Insert status content into props of the item.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef insert_status_in_props(item: TypeWithProps, status: common.ImplementationStatus) -> None:\n\"\"\"Insert status content into props of the item.\"\"\"\n    prop = ControlInterface._status_as_prop(status)\n    ControlInterface._replace_prop(item, prop)\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.is_withdrawn","title":"is_withdrawn(control) staticmethod","text":"

                                    Determine if control is marked Withdrawn.

                                    Parameters:

                                    Name Type Description Default control cat.Control

                                    The control that may be marked withdrawn.

                                    required

                                    Returns:

                                    Type Description bool

                                    True if marked withdrawn, false otherwise.

                                    This is determined by property with name 'status' with value 'Withdrawn'.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef is_withdrawn(control: cat.Control) -> bool:\n\"\"\"\n    Determine if control is marked Withdrawn.\n\n    Args:\n        control: The control that may be marked withdrawn.\n\n    Returns:\n        True if marked withdrawn, false otherwise.\n\n    This is determined by property with name 'status' with value 'Withdrawn'.\n    \"\"\"\n    for _ in as_filtered_list(\n            control.props,\n            lambda p: strip_lower_equals(p.name, 'status') and strip_lower_equals(p.value, 'withdrawn')):\n        return True\n    return False\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.item_has_rules","title":"item_has_rules(item) staticmethod","text":"

                                    Determine if the item has rules in its props.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef item_has_rules(item: TypeWithProps) -> bool:\n\"\"\"Determine if the item has rules in its props.\"\"\"\n    _, rules_props = ControlInterface.get_rules_dict_from_item(item)\n    return bool(rules_props)\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_dicts_deep","title":"merge_dicts_deep(dest, src, overwrite_header_values, depth=0, level=0) staticmethod","text":"

                                    Merge dict src into dest.

                                    New items are always added from src to dest. Items present in both will be overriden dest if overwrite_header_values is True.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef merge_dicts_deep(\n    dest: Dict[Any, Any],\n    src: Dict[Any, Any],\n    overwrite_header_values: bool,\n    depth: int = 0,\n    level: int = 0\n) -> None:\n\"\"\"\n    Merge dict src into dest.\n\n    New items are always added from src to dest.\n    Items present in both will be overriden dest if overwrite_header_values is True.\n    \"\"\"\n    for key in src.keys():\n        if key in dest:\n            if depth and level == depth:\n                if overwrite_header_values:\n                    dest[key] = src[key]\n                continue\n            # if they are both dicts, recurse\n            if isinstance(dest[key], dict) and isinstance(src[key], dict):\n                ControlInterface.merge_dicts_deep(dest[key], src[key], overwrite_header_values, depth, level + 1)\n            # if they are both lists, add any item that is not already in the list\n            elif isinstance(dest[key], list) and isinstance(src[key], list):\n                for item in src[key]:\n                    if item not in dest[key]:\n                        dest[key].append(item)\n            # otherwise override dest if needed\n            elif overwrite_header_values:\n                dest[key] = src[key]\n        else:\n            # if the item was not already in dest, add it from src\n            dest[key] = src[key]\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_part","title":"merge_part(dest, src) staticmethod","text":"

                                    Merge a source part into the destination part.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef merge_part(dest: common.Part, src: common.Part) -> common.Part:\n\"\"\"Merge a source part into the destination part.\"\"\"\n    dest.name = src.name if src.name else dest.name\n    dest.ns = src.ns if src.ns else dest.ns\n    dest.props = none_if_empty(ControlInterface.merge_props(dest.props, src.props))\n    dest.prose = src.prose\n    dest.title = src.title if src.title else dest.title\n    ControlInterface.merge_parts(dest, src)\n    return dest\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_parts","title":"merge_parts(dest, src) staticmethod","text":"

                                    Merge the parts from the source into the destination.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef merge_parts(dest: TypeWithParts, src: TypeWithParts) -> None:\n\"\"\"Merge the parts from the source into the destination.\"\"\"\n    if not dest.parts:\n        dest.parts = src.parts\n    elif not src.parts:\n        dest.parts = None\n    else:\n        new_parts: List[common.Part] = []\n        dest_map = {part.id: part for part in dest.parts}\n        for src_part in src.parts:\n            dest_part = dest_map.get(src_part.id, None)\n            if not dest_part:\n                new_parts.append(src_part)\n            else:\n                new_part = ControlInterface.merge_part(dest_part, src_part)\n                if new_part:\n                    new_parts.append(new_part)\n        dest.parts = new_parts\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_props","title":"merge_props(dest, src) staticmethod","text":"

                                    Merge a source list of properties into a destination list.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef merge_props(dest: Optional[List[common.Property]],\n                src: Optional[List[common.Property]]) -> List[common.Property]:\n\"\"\"Merge a source list of properties into a destination list.\"\"\"\n    if not src:\n        return dest\n    new_props: List[common.Property] = []\n    src_map = {prop.name: prop for prop in src}\n    dest_map = {prop.name: prop for prop in dest}\n    all_names = set(src_map.keys()).union(dest_map.keys())\n    for name in sorted(all_names):\n        if name in src_map and name not in dest_map:\n            new_props.append(src_map[name])\n        elif name in dest_map and name not in src_map:\n            new_props.append(dest_map[name])\n        else:\n            new_prop = dest_map[name]\n            src_prop = src_map[name]\n            new_prop.class_ = src_prop.class_ if src_prop.class_ else new_prop.class_\n            new_prop.ns = src_prop.ns if src_prop.ns else new_prop.ns\n            new_prop.remarks = src_prop.remarks if src_prop.remarks else new_prop.remarks\n            new_prop.uuid = src_prop.uuid if src_prop.uuid else new_prop.uuid\n            new_prop.value = src_prop.value\n            new_props.append(new_prop)\n    return new_props\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.param_to_str","title":"param_to_str(param, param_rep, verbose=False, brackets=False, params_format=None, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                    Convert parameter to string based on best available representation.

                                    Parameters:

                                    Name Type Description Default param common.Parameter

                                    the parameter to convert

                                    required param_rep ParameterRep

                                    how to represent the parameter

                                    required verbose bool

                                    provide verbose text for selection choices

                                    False brackets bool

                                    add brackets around the lists of items

                                    False params_format Optional[str]

                                    a string containing a single dot that represents a form of highlighting around the param

                                    None value_assigned_prefix Optional[str]

                                    string to place before the parameter string if a value was assigned

                                    None value_not_assigned_prefix Optional[str]

                                    string to place before the parameter string if value not assigned

                                    None

                                    Returns:

                                    Type Description Optional[str]

                                    formatted string or None

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef param_to_str(\n    param: common.Parameter,\n    param_rep: ParameterRep,\n    verbose: bool = False,\n    brackets: bool = False,\n    params_format: Optional[str] = None,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> Optional[str]:\n\"\"\"\n    Convert parameter to string based on best available representation.\n\n    Args:\n        param: the parameter to convert\n        param_rep: how to represent the parameter\n        verbose: provide verbose text for selection choices\n        brackets: add brackets around the lists of items\n        params_format: a string containing a single dot that represents a form of highlighting around the param\n        value_assigned_prefix: string to place before the parameter string if a value was assigned\n        value_not_assigned_prefix: string to place before the parameter string if value not assigned\n\n    Returns:\n        formatted string or None\n    \"\"\"\n    param_str = None\n    if param_rep == ParameterRep.VALUE_OR_STRING_NONE:\n        param_str = ControlInterface._param_values_as_str(param)\n        param_str = param_str if param_str else 'None'\n    elif param_rep == ParameterRep.LABEL_OR_CHOICES:\n        param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n    elif param_rep == ParameterRep.VALUE_OR_LABEL_OR_CHOICES:\n        param_str = ControlInterface._param_values_as_str(param)\n        if not param_str:\n            param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n    elif param_rep == ParameterRep.VALUE_OR_EMPTY_STRING:\n        param_str = ControlInterface._param_values_as_str(param, brackets)\n        if not param_str:\n            param_str = ''\n    elif param_rep == ParameterRep.ASSIGNMENT_FORM:\n        param_str = ControlInterface._param_values_assignment_str(\n            param, value_assigned_prefix, value_not_assigned_prefix\n        )\n        if not param_str:\n            param_str = ''\n    elif param_rep == ParameterRep.LABEL_FORM:\n        param_str = ControlInterface._param_labels_assignment_str(param, value_not_assigned_prefix)\n        if not param_str:\n            param_str = ''\n    return ControlInterface._apply_params_format(param_str, params_format)\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.replace_control_prose","title":"replace_control_prose(control, param_dict, params_format=None, param_rep=<ParameterRep.VALUE_OR_LABEL_OR_CHOICES: 3>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                    Replace the control prose according to set_param.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef replace_control_prose(\n    control: cat.Control,\n    param_dict: Dict[str, common.Parameter],\n    params_format: Optional[str] = None,\n    param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> None:\n\"\"\"Replace the control prose according to set_param.\"\"\"\n    # first replace all choices that reference parameters\n    # note that in ASSIGNMENT_FORM each choice with a parameter will end up as [Assignment: value]\n    for param in as_list(control.params):\n        ControlInterface._replace_param_choices(\n            param,\n            param_dict,\n            params_format,\n            param_rep,\n            show_value_warnings,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n    for part in as_list(control.parts):\n        if part.prose is not None:\n            fixed_prose = ControlInterface._replace_params(\n                part.prose,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n            # change the prose in the control itself\n            part.prose = fixed_prose\n        for prt in as_list(part.parts):\n            ControlInterface._replace_part_prose(\n                control,\n                prt,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.setparam_to_param","title":"setparam_to_param(param_id, set_param) staticmethod","text":"

                                    Convert setparameter to parameter.

                                    Parameters:

                                    Name Type Description Default param_id str

                                    the id of the parameter

                                    required set_param prof.SetParameter

                                    the set_parameter from a profile

                                    required

                                    Returns:

                                    Type Description common.Parameter

                                    a Parameter with param_id and content from the SetParameter

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef setparam_to_param(param_id: str, set_param: prof.SetParameter) -> common.Parameter:\n\"\"\"\n    Convert setparameter to parameter.\n\n    Args:\n        param_id: the id of the parameter\n        set_param: the set_parameter from a profile\n\n    Returns:\n        a Parameter with param_id and content from the SetParameter\n    \"\"\"\n    return common.Parameter(\n        id=param_id, values=set_param.values, select=set_param.select, label=set_param.label, props=set_param.props\n    )\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.strip_to_make_ncname","title":"strip_to_make_ncname(label) staticmethod","text":"

                                    Strip chars to conform with NCNAME regex.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef strip_to_make_ncname(label: str) -> str:\n\"\"\"Strip chars to conform with NCNAME regex.\"\"\"\n    orig_label = label\n    # make sure first char is allowed\n    while label and label[0] not in const.NCNAME_UTF8_FIRST_CHAR_OPTIONS:\n        label = label[1:]\n    new_label = label[:1]\n    # now check remaining chars\n    if len(label) > 1:\n        for ii in range(1, len(label)):\n            if label[ii] in const.NCNAME_UTF8_OTHER_CHAR_OPTIONS:\n                new_label += label[ii]\n    # do final check to confirm it is NCNAME\n    match = re.search(const.NCNAME_REGEX, new_label)\n    if not match:\n        raise TrestleError(f'Unable to convert label {orig_label} to NCNAME format.')\n    return new_label\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.uniquify_set_params","title":"uniquify_set_params(set_params) staticmethod","text":"

                                    Remove items with same param_id with priority to later items.

                                    Source code in trestle/core/control_interface.py
                                    @staticmethod\ndef uniquify_set_params(set_params: Optional[List[TypeWithParamId]]) -> List[TypeWithParamId]:\n\"\"\"Remove items with same param_id with priority to later items.\"\"\"\n    found_ids: Set[str] = set()\n    unique_list: List[TypeWithParamId] = []\n    for set_param in reversed(as_list(set_params)):\n        if set_param.param_id not in found_ids:\n            unique_list.append(set_param)\n            found_ids.add(set_param.param_id)\n    return list(reversed(unique_list))\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep","title":" ParameterRep (Enum) ","text":"

                                    Enum for ways to represent a parameter.

                                    Source code in trestle/core/control_interface.py
                                    class ParameterRep(Enum):\n\"\"\"Enum for ways to represent a parameter.\"\"\"\n\n    LEAVE_MOUSTACHE = 0\n    VALUE_OR_STRING_NONE = 1\n    LABEL_OR_CHOICES = 2\n    VALUE_OR_LABEL_OR_CHOICES = 3\n    VALUE_OR_EMPTY_STRING = 4\n    ASSIGNMENT_FORM = 5\n    LABEL_FORM = 6\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.ASSIGNMENT_FORM","title":"ASSIGNMENT_FORM","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.LABEL_FORM","title":"LABEL_FORM","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.LABEL_OR_CHOICES","title":"LABEL_OR_CHOICES","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.LEAVE_MOUSTACHE","title":"LEAVE_MOUSTACHE","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.VALUE_OR_EMPTY_STRING","title":"VALUE_OR_EMPTY_STRING","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.VALUE_OR_LABEL_OR_CHOICES","title":"VALUE_OR_LABEL_OR_CHOICES","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.VALUE_OR_STRING_NONE","title":"VALUE_OR_STRING_NONE","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo","title":" PartInfo dataclass","text":"

                                    Class to capture control part info needed in markdown.

                                    Source code in trestle/core/control_interface.py
                                    @dataclass\nclass PartInfo:\n\"\"\"Class to capture control part info needed in markdown.\"\"\"\n\n    name: str\n    prose: str\n    smt_part: str = ''\n    props: Optional[List[common.Property]] = None\n    parts: Optional[List[PartInfo]] = None\n\n    def to_dicts(self, part_id_map: Dict[str, str]) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:\n\"\"\"Convert the part info to a dict or list of props.\"\"\"\n        prop_list = []\n        part = {}\n        # if it has a part name then it is a part with prose\n        if self.name:\n            part['name'] = part_id_map.get(self.name, self.name)\n            if self.prose:\n                part['prose'] = self.prose\n            if self.parts:\n                all_subparts = []\n                for subpart in self.parts:\n                    subpart_dict, _ = subpart.to_dicts(part_id_map)\n                    all_subparts.append(subpart_dict)\n                part['parts'] = all_subparts\n\n        # otherwise it is a list of props\n        else:\n            for prop in as_list(self.props):\n                prop_d = {'name': prop.name, 'value': prop.value}\n                if prop.ns:\n                    prop_d['ns'] = str(prop.ns)\n                if self.smt_part:\n                    prop_d['smt-part'] = part_id_map.get(self.smt_part, self.smt_part)\n                prop_list.append(prop_d)\n        return part, prop_list\n
                                    "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.name","title":"name: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.parts","title":"parts: Optional[List[trestle.core.control_interface.PartInfo]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.props","title":"props: Optional[List[trestle.oscal.common.Property]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.prose","title":"prose: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.smt_part","title":"smt_part: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.__init__","title":"__init__(self, name, prose, smt_part='', props=None, parts=None) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.to_dicts","title":"to_dicts(self, part_id_map)","text":"

                                    Convert the part info to a dict or list of props.

                                    Source code in trestle/core/control_interface.py
                                    def to_dicts(self, part_id_map: Dict[str, str]) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:\n\"\"\"Convert the part info to a dict or list of props.\"\"\"\n    prop_list = []\n    part = {}\n    # if it has a part name then it is a part with prose\n    if self.name:\n        part['name'] = part_id_map.get(self.name, self.name)\n        if self.prose:\n            part['prose'] = self.prose\n        if self.parts:\n            all_subparts = []\n            for subpart in self.parts:\n                subpart_dict, _ = subpart.to_dicts(part_id_map)\n                all_subparts.append(subpart_dict)\n            part['parts'] = all_subparts\n\n    # otherwise it is a list of props\n    else:\n        for prop in as_list(self.props):\n            prop_d = {'name': prop.name, 'value': prop.value}\n            if prop.ns:\n                prop_d['ns'] = str(prop.ns)\n            if self.smt_part:\n                prop_d['smt-part'] = part_id_map.get(self.smt_part, self.smt_part)\n            prop_list.append(prop_d)\n    return part, prop_list\n
                                    "},{"location":"api_reference/trestle.core.control_reader/","title":"control_reader","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader","title":"trestle.core.control_reader","text":"

                                    Handle reading of writing controls from markdown.

                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader","title":" ControlReader ","text":"

                                    Class to read controls from markdown.

                                    Source code in trestle/core/control_reader.py
                                    class ControlReader:\n\"\"\"Class to read controls from markdown.\"\"\"\n\n    @staticmethod\n    def _clean_prose(prose: List[str]) -> List[str]:\n        # remove empty and horizontal rule lines at start and end of list of prose lines\n        forward_index = 0\n        for line in prose:\n            if line.strip() and not line.startswith('____'):\n                break\n            forward_index += 1\n        new_prose = prose[forward_index:]\n        reverse_index = 0\n        for line in reversed(new_prose):\n            if line.strip() and not line.startswith('____'):\n                break\n            reverse_index += 1\n        clean_prose = new_prose[:len(new_prose) - reverse_index]\n        clean_prose = clean_prose if clean_prose else ['']\n        # if there is no useful prose this will return [''] and allow generation of a statement with empty prose\n        return clean_prose\n\n    @staticmethod\n    def _comp_name_in_dict(comp_name: str, comp_dict: CompDict) -> str:\n\"\"\"If the name is already in the dict in a similar form, stick to that form.\"\"\"\n        simple_name = ControlReader.simplify_name(comp_name)\n        for name in comp_dict.keys():\n            if simple_name == ControlReader.simplify_name(name):\n                return name\n        return comp_name\n\n    @staticmethod\n    def _add_node_to_dict(\n        comp_name: Optional[str],\n        label: str,\n        comp_dict: CompDict,\n        node: ControlMarkdownNode,\n        control_id: str,\n        comp_list: List[str],\n        context: ControlContext\n    ) -> None:\n\"\"\"\n        Extract the label, prose, possible component name - along with implementation status.\n\n        In component mode there is only one component and its name is not in markdown.\n        In ssp mode there are many components in each md file.\n        \"\"\"\n        component_mode = context.purpose == ContextPurpose.COMPONENT\n        # for ssp, ### marks component name but for component it is ##\n        # if it is a header, make sure it has correct format\n        if node.key and node.key[0] == '#' and ControlInterface.bad_header(node.key):\n            raise TrestleError(f'Improper header format for control {control_id}: {node.key}')\n        if not component_mode:\n            # look for component name heading if present\n            prefix = '### '\n            if node.key.startswith(prefix):\n                if len(node.key.split()) <= 1:\n                    raise TrestleError(\n                        f'Header line in control {control_id} markdown starts with {prefix} but has no content.'\n                    )\n                comp_name = node.key.split(' ', 1)[1].strip()\n                simp_comp_name = ControlReader.simplify_name(comp_name)\n                if simp_comp_name in comp_list:\n                    raise TrestleError(\n                        f'Control {control_id} has a section with two component headings for {comp_name}.  '\n                        'Please combine the sections so there is only one heading for each component in a '\n                        'statement.'\n                    )\n                comp_list.append(simp_comp_name)\n                comp_name = ControlReader._comp_name_in_dict(comp_name, comp_dict)\n\n        # prose may be empty in md and we want to capture that so put it in the comp_dict\n        prose = '\\n'.join(ControlReader._clean_prose(node.content.text))\n        # add the prose to the comp_dict, creating new entry as needed\n        if comp_name in comp_dict:\n            if label in comp_dict[comp_name]:\n                comp_dict[comp_name][label].prose = prose\n            else:\n                # create new entry with prose\n                comp_dict[comp_name][label] = ComponentImpInfo(prose=prose, rules=[], props=[])\n        elif comp_name:\n            comp_dict[comp_name] = {label: ComponentImpInfo(prose=prose, rules=[], props=[])}\n\n        # build list of subnodes that get handled specially so they aren't processed here\n        subnode_kill: List[int] = []\n        status_str = None\n        remarks_str = None\n        rules_list: List[str] = []\n        for ii, subnode in enumerate(node.subnodes):\n            if subnode.key.find(const.IMPLEMENTATION_STATUS_REMARKS_HEADER) >= 0:\n                remarks_str = subnode.key.split(maxsplit=4)[-1]\n                subnode_kill.append(ii)\n            elif subnode.key.find(const.IMPLEMENTATION_STATUS_HEADER) >= 0:\n                status_str = subnode.key.split(maxsplit=3)[-1]\n                subnode_kill.append(ii)\n            elif subnode.key.find('Rules:') >= 0:\n                rules_list = [text[2:] for text in subnode.content.text if text.startswith('- ')]\n                subnode_kill.append(ii)\n        if status_str:\n            new_status = common.ImplementationStatus(state=status_str, remarks=remarks_str)\n            if comp_name not in comp_dict:\n                comp_dict[comp_name] = {}\n            if label not in comp_dict[comp_name]:\n                comp_dict[comp_name][label] = ComponentImpInfo(prose='', rules=[], props=[])\n            comp_dict[comp_name][label].status = new_status\n        if rules_list:\n            comp_dict[comp_name][label].rules = rules_list\n        delete_list_from_list(node.subnodes, subnode_kill)\n        for subnode in as_list(node.subnodes):\n            ControlReader._add_node_to_dict(comp_name, label, comp_dict, subnode, control_id, comp_list, context)\n\n    @staticmethod\n    def _insert_header_content(\n        imp_req: generic.GenericImplementedRequirement, header: Dict[str, Any], control_id: str\n    ) -> None:\n\"\"\"Insert yaml header content into the imp_req and its by_comps as props.\"\"\"\n        dict_ = header.get(const.TRESTLE_PROPS_TAG, {})\n        roles = as_list(dict_.get(const.RESPONSIBLE_ROLES, []))\n        props = []\n        responsible_roles = []\n        for role in roles:\n            if isinstance(role, str):\n                # role_id must conform to NCNAME regex\n                role = role.strip().replace(' ', '_')\n                if role:\n                    responsible_roles.append(common.ResponsibleRole(role_id=role))\n            else:\n                logger.warning(f'Role in header for control {control_id} not recognized: {role}')\n        if props:\n            imp_req.props = as_list(imp_req.props)\n            imp_req.props.extend(props)\n        if responsible_roles:\n            imp_req.responsible_roles = as_list(imp_req.responsible_roles)\n            imp_req.responsible_roles.extend(responsible_roles)\n            imp_req.responsible_roles = none_if_empty(imp_req.responsible_roles)\n            # enforce single list of resp. roles for control and each by_comp\n            for by_comp in as_list(imp_req.by_components):\n                by_comp.responsible_roles = imp_req.responsible_roles\n\n    @staticmethod\n    def simplify_name(name: str) -> str:\n\"\"\"Simplify the name to ignore variations in case, space, hyphen, underscore, slash.\"\"\"\n        return name.lower().replace(' ', '').replace('-', '').replace('_', '').replace('/', '')\n\n    @staticmethod\n    def _get_label_from_implementation_header(imp_header: str):\n        # assumed to be of form: Implementation for part a.\n        split_header = imp_header.split(' ', 4)\n        if len(split_header) != 5:\n            raise TrestleError(f'Implementation header cannot be parsed for statement part: {imp_header}')\n        return split_header[4].strip()\n\n    @staticmethod\n    def read_control_info_from_md(control_file: pathlib.Path,\n                                  context: ControlContext) -> Tuple[Dict[str, List[str]], CompDict]:\n\"\"\"\n        Find all labels and associated implementation prose in the markdown for this control.\n\n        Args:\n            control_file: path to the control markdown file\n            context: context of the control usage\n\n        Returns:\n            The yaml header as dict in second part of tuple.\n            Adds to the passed in comp_dict.\n        \"\"\"\n        yaml_header = {}\n        comp_dict = {}\n\n        if not control_file.exists():\n            return yaml_header, comp_dict\n        # if the file exists, load the contents but do not use prose from comp_dict\n        # for non ssp or component mode just use empty string for comp\n        comp_name = ''\n        try:\n            control_id = control_file.stem\n            if context.purpose == ContextPurpose.COMPONENT:\n                comp_name = context.comp_name if context.comp_name else const.SSP_MAIN_COMP_NAME\n\n            md_api = MarkdownAPI()\n            yaml_header, control_md = md_api.processor.process_markdown(control_file)\n\n            # first get the header strings, including statement labels, for statement imp reqs\n            imp_string = '## Implementation '\n            headers = control_md.get_all_headers_for_level(2)\n            # get e.g. ## Implementation a.  ## Implementation b. etc\n            imp_header_list = [header for header in headers if header.startswith(imp_string)]\n\n            # now get the (one) header for the main solution\n            main_headers = list(control_md.get_all_headers_for_key(const.SSP_MD_IMPLEMENTATION_QUESTION, False))\n            # should be only one header, so warn if others found\n            if main_headers:\n                if len(main_headers) > 1:\n                    logger.warning(\n                        f'Control {control_id} has {len(main_headers)} main header responses.  Will use first one only.'\n                    )\n                main_header = main_headers[0]\n                node = control_md.get_all_nodes_for_keys([main_header], False)[0]\n                # this node is top level so it will have empty label\n                # it may have subnodes of Rules, Implementation Status, Implementaton Remarks\n                ControlReader._add_node_to_dict(comp_name, '', comp_dict, node, control_id, [], context)\n            for imp_header in imp_header_list:\n                label = ControlReader._get_label_from_implementation_header(imp_header)\n                node = control_md.get_node_for_key(imp_header)\n                ControlReader._add_node_to_dict(comp_name, label, comp_dict, node, control_id, [], context)\n\n        except TrestleError as e:\n            raise TrestleError(f'Error occurred reading {control_file}: {e}')\n        return yaml_header, comp_dict\n\n    @staticmethod\n    def _handle_empty_prose(prose: str, id_: str) -> str:\n\"\"\"Regard prompt text or id_ as no prose and return blank string.\"\"\"\n        if prose.startswith(const.SSP_ADD_IMPLEMENTATION_PREFIX) or prose == id_:\n            return ''\n        return prose\n\n    @staticmethod\n    def read_implemented_requirement(control_file: pathlib.Path,\n                                     context: ControlContext) -> Tuple[str, comp.ImplementedRequirement]:\n\"\"\"\n        Get the implementated requirement associated with given control and link to existing components or new ones.\n\n        Args:\n            control_file: path of the control markdown file\n            context: context of the control usage\n\n        Returns:\n            Tuple: The control sort-id and the one implemented requirement for this control.\n\n        Notes:\n            Each statement may have several responses, with each response in a by_component for a specific component.\n            statement_map keeps track of statements that may have several by_component responses.\n            This is only used during component assemble and only for updating one component.\n        \"\"\"\n        control_id = control_file.stem\n        md_header, md_comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n        comp_name = context.component.title\n\n        statement_map: Dict[str, comp.Statement] = {}\n        # create a new implemented requirement linked to the control id to hold the statements\n        imp_req = gens.generate_sample_model(comp.ImplementedRequirement)\n        imp_req.control_id = control_id\n\n        imp_req.statements = []\n        comp_dict = md_comp_dict[comp_name]\n        for label, comp_info in comp_dict.items():\n            # only assemble responses with associated rules\n            if not comp_info.rules:\n                continue\n            # if no label it applies to the imp_req itself rather than a statement\n            if not label:\n                imp_req.description = ControlReader._handle_empty_prose(comp_info.prose, control_id)\n                ControlInterface.insert_status_in_props(imp_req, comp_info.status)\n                continue\n            statement_id = ControlInterface.create_statement_id(control_id)\n            if label in ['', const.STATEMENT]:\n                statement_part_id = statement_id\n            else:\n                clean_label = label.strip('.')\n                statement_part_id = ControlInterface.strip_to_make_ncname(f'{statement_id}.{clean_label}')\n            if statement_part_id in statement_map:\n                statement = statement_map[statement_part_id]\n            else:\n                statement = gens.generate_sample_model(comp.Statement)\n                statement.statement_id = statement_part_id\n                statement_map[statement_part_id] = statement\n            statement.description = comp_info.prose\n            statement.props = none_if_empty(ControlInterface.clean_props(comp_info.props))\n            ControlInterface.insert_status_in_props(statement, comp_info.status)\n\n        imp_req.statements = list(statement_map.values())\n        imp_req.set_parameters = []\n\n        for _, param_dict_list in md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {}).items():\n            for param_dict in param_dict_list:\n                values = param_dict.get(const.VALUES, [])\n                comp_values = param_dict.get(const.COMPONENT_VALUES, [])\n                values = comp_values if comp_values else values\n                set_param = ossp.SetParameter(param_id=param_dict['name'], values=values)\n                imp_req.set_parameters.append(set_param)\n        imp_req.statements = none_if_empty(list(statement_map.values()))\n        imp_req.set_parameters = none_if_empty(imp_req.set_parameters)\n\n        ControlReader._insert_header_content(imp_req, md_header, control_id)\n        sort_id = md_header.get(const.SORT_ID, control_id)\n        return sort_id, imp_req\n\n    @staticmethod\n    def get_props_list(control_id: str, label_map: Dict[str, str],\n                       yaml_header: Dict[str, Any]) -> Tuple[List[common.Property], Dict[str, List[common.Property]]]:\n\"\"\"Get the list of props in the yaml header of this control as separate lists with and without by_id.\"\"\"\n        prop_list = yaml_header.get(const.TRESTLE_ADD_PROPS_TAG, [])\n        props = []\n        props_by_id = {}\n        for prop_d in prop_list:\n            by_id = prop_d.get('smt-part', None)\n            if by_id and control_id in label_map:\n                by_id = label_map[control_id].get(by_id, by_id)\n            prop = common.Property(name=prop_d['name'], value=prop_d['value'], ns=prop_d.get('ns', None))\n            if by_id:\n                if by_id not in props_by_id:\n                    props_by_id[by_id] = []\n                props_by_id[by_id].append(prop)\n            else:\n                props.append(prop)\n        return props, props_by_id\n\n    @staticmethod\n    def read_editable_content(\n        control_path: pathlib.Path,\n        required_sections_list: List[str],\n        part_label_to_id_map: Dict[str, Dict[str, str]],\n        cli_section_dict: Dict[str, str],\n        write_mode: bool\n    ) -> Tuple[str, List[prof.Alter], Dict[str, Any]]:\n\"\"\"Get parts for the markdown control corresponding to Editable Content - along with the set-parameter dict.\"\"\"\n        control_id = control_path.stem\n\n        md_api = MarkdownAPI()\n        yaml_header, control_tree = md_api.processor.process_control_markdown(control_path, cli_section_dict, part_label_to_id_map)  # noqa: E501\n        # extract the sort_id if present in header\n        sort_id = yaml_header.get(const.SORT_ID, control_id)\n\n        editable_node = None\n        for header in list(control_tree.get_all_headers_for_level(1)):\n            if header.startswith('# Editable'):\n                editable_node = control_tree.get_node_for_key(header)\n                break\n        if not editable_node:\n            return sort_id, [], {}\n\n        editable_parts = control_tree.get_editable_parts_and_subparts()\n        by_id_parts = control_tree.get_by_id_parts()\n        found_sections = [p.name for p in editable_parts]\n\n        # Validate that all required sections have a prose\n        for editable_part in editable_parts:\n            if not write_mode and editable_part.name in required_sections_list and editable_part.prose.startswith(\n                    const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT):\n                raise TrestleError(f'Control {control_id} is missing prose for required section {editable_part.title}')\n\n        # Validate that all required sections are present\n        missing_sections = set(required_sections_list) - set(found_sections)\n        if missing_sections:\n            raise TrestleError(f'Control {control_id} is missing required sections {missing_sections}')\n        param_dict: Dict[str, Any] = {}\n        # get set_params from the header and add to parm_dict\n        header_params = yaml_header.get(const.SET_PARAMS_TAG, {})\n        if header_params:\n            param_dict.update(header_params)\n\n        props, props_by_id = ControlReader.get_props_list(control_id, part_label_to_id_map, yaml_header)\n\n        # When adding props without by_id it can either be starting or ending and we default to ending\n        # This is the default behavior as described for implicit binding in\n        # https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/\n        # When adding props to a part using by_id, it is the same situation because it cannot be before or after since\n        # props are not in the same list as parts\n\n        adds: List[prof.Add] = []\n\n        # add the parts and props at control level\n        if editable_parts or props:\n            adds.append(\n                prof.Add(\n                    parts=none_if_empty(editable_parts),\n                    props=none_if_empty(props),\n                    position=prof.PositionValidValues.ending.value\n                )\n            )\n\n        # add the parts and props at the part level, by-id\n        by_ids = set(by_id_parts.keys()).union(props_by_id.keys())\n        for by_id in sorted(by_ids):\n            parts = by_id_parts.get(by_id, None)\n            props = props_by_id.get(by_id, None)\n            adds.append(prof.Add(parts=parts, props=props, position=prof.PositionValidValues.ending.value, by_id=by_id))\n\n        new_alters = []\n        if adds:\n            new_alters = [prof.Alter(control_id=control_id, adds=adds)]\n        return sort_id, new_alters, param_dict\n\n    @staticmethod\n    def _update_display_prop_namespace(item: TypeWithProps):\n\"\"\"Set namespace for special property display_name.\"\"\"\n        for prop in as_list(item.props):\n            if prop.name == const.DISPLAY_NAME:\n                prop.ns = const.TRESTLE_GENERIC_NS\n\n    @staticmethod\n    def read_control(control_path: pathlib.Path, set_parameters_flag: bool) -> Tuple[cat.Control, str]:\n\"\"\"Read the control and group title from the markdown file.\"\"\"\n        control = gens.generate_sample_model(cat.Control)\n        md_api = MarkdownAPI()\n        yaml_header, control_tree = md_api.processor.process_control_markdown(control_path)\n        control_titles = list(control_tree.get_all_headers_for_level(1))\n        if len(control_titles) == 0:\n            raise TrestleError(f'Control markdown: {control_path} contains no control title.')\n        if len(control_titles) > 1:\n            raise TrestleError(f'Control markdown: {control_path} contains multiple control titles {control_titles}.')\n\n        control.id = control_tree.subnodes[0].content.control_id\n        group_title = control_tree.subnodes[0].content.control_group\n        control.title = control_tree.subnodes[0].content.control_title\n\n        control_statement = control_tree.get_control_statement()\n        statement_part = control_statement.content.part\n\n        control.parts = [statement_part] if statement_part else None\n        control_objective = control_tree.get_control_objective()\n        if control_objective is not None:\n            objective_part = control_objective.content.part\n            if objective_part:\n                if control.parts:\n                    control.parts.append(objective_part)\n                else:\n                    control.parts = [objective_part]\n\n        control_guidance = control_tree.get_control_guidance()\n        if control_guidance is not None:\n            guidance_part = control_guidance.content.part\n            if guidance_part:\n                if control.parts:\n                    control.parts.append(guidance_part)\n                else:\n                    control.parts = [guidance_part]\n\n        all_other_parts = []\n        for section_node in control_tree.get_other_control_parts():\n            parts = section_node.content.part\n            all_other_parts.extend([parts])\n        if all_other_parts:\n            if control.parts:\n                control.parts.extend(all_other_parts)\n            else:\n                control.parts = all_other_parts\n\n        if set_parameters_flag:\n            params: Dict[str, str] = yaml_header.get(const.SET_PARAMS_TAG, [])\n            if params:\n                control.params = []\n                for id_, param_dict in params.items():\n                    param_dict['id'] = id_\n                    param = ModelUtils.dict_to_parameter(param_dict)\n                    # if display_name is in list of properties, set its namespace\n                    ControlReader._update_display_prop_namespace(param)\n                    control.params.append(param)\n        sort_id = deep_get(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], None)\n        if sort_id:\n            control.props = control.props if control.props else []\n            control.props.append(common.Property(name=const.SORT_ID, value=sort_id))\n        return control, group_title\n
                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.get_props_list","title":"get_props_list(control_id, label_map, yaml_header) staticmethod","text":"

                                    Get the list of props in the yaml header of this control as separate lists with and without by_id.

                                    Source code in trestle/core/control_reader.py
                                    @staticmethod\ndef get_props_list(control_id: str, label_map: Dict[str, str],\n                   yaml_header: Dict[str, Any]) -> Tuple[List[common.Property], Dict[str, List[common.Property]]]:\n\"\"\"Get the list of props in the yaml header of this control as separate lists with and without by_id.\"\"\"\n    prop_list = yaml_header.get(const.TRESTLE_ADD_PROPS_TAG, [])\n    props = []\n    props_by_id = {}\n    for prop_d in prop_list:\n        by_id = prop_d.get('smt-part', None)\n        if by_id and control_id in label_map:\n            by_id = label_map[control_id].get(by_id, by_id)\n        prop = common.Property(name=prop_d['name'], value=prop_d['value'], ns=prop_d.get('ns', None))\n        if by_id:\n            if by_id not in props_by_id:\n                props_by_id[by_id] = []\n            props_by_id[by_id].append(prop)\n        else:\n            props.append(prop)\n    return props, props_by_id\n
                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_control","title":"read_control(control_path, set_parameters_flag) staticmethod","text":"

                                    Read the control and group title from the markdown file.

                                    Source code in trestle/core/control_reader.py
                                    @staticmethod\ndef read_control(control_path: pathlib.Path, set_parameters_flag: bool) -> Tuple[cat.Control, str]:\n\"\"\"Read the control and group title from the markdown file.\"\"\"\n    control = gens.generate_sample_model(cat.Control)\n    md_api = MarkdownAPI()\n    yaml_header, control_tree = md_api.processor.process_control_markdown(control_path)\n    control_titles = list(control_tree.get_all_headers_for_level(1))\n    if len(control_titles) == 0:\n        raise TrestleError(f'Control markdown: {control_path} contains no control title.')\n    if len(control_titles) > 1:\n        raise TrestleError(f'Control markdown: {control_path} contains multiple control titles {control_titles}.')\n\n    control.id = control_tree.subnodes[0].content.control_id\n    group_title = control_tree.subnodes[0].content.control_group\n    control.title = control_tree.subnodes[0].content.control_title\n\n    control_statement = control_tree.get_control_statement()\n    statement_part = control_statement.content.part\n\n    control.parts = [statement_part] if statement_part else None\n    control_objective = control_tree.get_control_objective()\n    if control_objective is not None:\n        objective_part = control_objective.content.part\n        if objective_part:\n            if control.parts:\n                control.parts.append(objective_part)\n            else:\n                control.parts = [objective_part]\n\n    control_guidance = control_tree.get_control_guidance()\n    if control_guidance is not None:\n        guidance_part = control_guidance.content.part\n        if guidance_part:\n            if control.parts:\n                control.parts.append(guidance_part)\n            else:\n                control.parts = [guidance_part]\n\n    all_other_parts = []\n    for section_node in control_tree.get_other_control_parts():\n        parts = section_node.content.part\n        all_other_parts.extend([parts])\n    if all_other_parts:\n        if control.parts:\n            control.parts.extend(all_other_parts)\n        else:\n            control.parts = all_other_parts\n\n    if set_parameters_flag:\n        params: Dict[str, str] = yaml_header.get(const.SET_PARAMS_TAG, [])\n        if params:\n            control.params = []\n            for id_, param_dict in params.items():\n                param_dict['id'] = id_\n                param = ModelUtils.dict_to_parameter(param_dict)\n                # if display_name is in list of properties, set its namespace\n                ControlReader._update_display_prop_namespace(param)\n                control.params.append(param)\n    sort_id = deep_get(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], None)\n    if sort_id:\n        control.props = control.props if control.props else []\n        control.props.append(common.Property(name=const.SORT_ID, value=sort_id))\n    return control, group_title\n
                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_control_info_from_md","title":"read_control_info_from_md(control_file, context) staticmethod","text":"

                                    Find all labels and associated implementation prose in the markdown for this control.

                                    Parameters:

                                    Name Type Description Default control_file Path

                                    path to the control markdown file

                                    required context ControlContext

                                    context of the control usage

                                    required

                                    Returns:

                                    Type Description Tuple[Dict[str, List[str]], Dict[str, Dict[str, trestle.core.control_interface.ComponentImpInfo]]]

                                    The yaml header as dict in second part of tuple. Adds to the passed in comp_dict.

                                    Source code in trestle/core/control_reader.py
                                    @staticmethod\ndef read_control_info_from_md(control_file: pathlib.Path,\n                              context: ControlContext) -> Tuple[Dict[str, List[str]], CompDict]:\n\"\"\"\n    Find all labels and associated implementation prose in the markdown for this control.\n\n    Args:\n        control_file: path to the control markdown file\n        context: context of the control usage\n\n    Returns:\n        The yaml header as dict in second part of tuple.\n        Adds to the passed in comp_dict.\n    \"\"\"\n    yaml_header = {}\n    comp_dict = {}\n\n    if not control_file.exists():\n        return yaml_header, comp_dict\n    # if the file exists, load the contents but do not use prose from comp_dict\n    # for non ssp or component mode just use empty string for comp\n    comp_name = ''\n    try:\n        control_id = control_file.stem\n        if context.purpose == ContextPurpose.COMPONENT:\n            comp_name = context.comp_name if context.comp_name else const.SSP_MAIN_COMP_NAME\n\n        md_api = MarkdownAPI()\n        yaml_header, control_md = md_api.processor.process_markdown(control_file)\n\n        # first get the header strings, including statement labels, for statement imp reqs\n        imp_string = '## Implementation '\n        headers = control_md.get_all_headers_for_level(2)\n        # get e.g. ## Implementation a.  ## Implementation b. etc\n        imp_header_list = [header for header in headers if header.startswith(imp_string)]\n\n        # now get the (one) header for the main solution\n        main_headers = list(control_md.get_all_headers_for_key(const.SSP_MD_IMPLEMENTATION_QUESTION, False))\n        # should be only one header, so warn if others found\n        if main_headers:\n            if len(main_headers) > 1:\n                logger.warning(\n                    f'Control {control_id} has {len(main_headers)} main header responses.  Will use first one only.'\n                )\n            main_header = main_headers[0]\n            node = control_md.get_all_nodes_for_keys([main_header], False)[0]\n            # this node is top level so it will have empty label\n            # it may have subnodes of Rules, Implementation Status, Implementaton Remarks\n            ControlReader._add_node_to_dict(comp_name, '', comp_dict, node, control_id, [], context)\n        for imp_header in imp_header_list:\n            label = ControlReader._get_label_from_implementation_header(imp_header)\n            node = control_md.get_node_for_key(imp_header)\n            ControlReader._add_node_to_dict(comp_name, label, comp_dict, node, control_id, [], context)\n\n    except TrestleError as e:\n        raise TrestleError(f'Error occurred reading {control_file}: {e}')\n    return yaml_header, comp_dict\n
                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_editable_content","title":"read_editable_content(control_path, required_sections_list, part_label_to_id_map, cli_section_dict, write_mode) staticmethod","text":"

                                    Get parts for the markdown control corresponding to Editable Content - along with the set-parameter dict.

                                    Source code in trestle/core/control_reader.py
                                    @staticmethod\ndef read_editable_content(\n    control_path: pathlib.Path,\n    required_sections_list: List[str],\n    part_label_to_id_map: Dict[str, Dict[str, str]],\n    cli_section_dict: Dict[str, str],\n    write_mode: bool\n) -> Tuple[str, List[prof.Alter], Dict[str, Any]]:\n\"\"\"Get parts for the markdown control corresponding to Editable Content - along with the set-parameter dict.\"\"\"\n    control_id = control_path.stem\n\n    md_api = MarkdownAPI()\n    yaml_header, control_tree = md_api.processor.process_control_markdown(control_path, cli_section_dict, part_label_to_id_map)  # noqa: E501\n    # extract the sort_id if present in header\n    sort_id = yaml_header.get(const.SORT_ID, control_id)\n\n    editable_node = None\n    for header in list(control_tree.get_all_headers_for_level(1)):\n        if header.startswith('# Editable'):\n            editable_node = control_tree.get_node_for_key(header)\n            break\n    if not editable_node:\n        return sort_id, [], {}\n\n    editable_parts = control_tree.get_editable_parts_and_subparts()\n    by_id_parts = control_tree.get_by_id_parts()\n    found_sections = [p.name for p in editable_parts]\n\n    # Validate that all required sections have a prose\n    for editable_part in editable_parts:\n        if not write_mode and editable_part.name in required_sections_list and editable_part.prose.startswith(\n                const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT):\n            raise TrestleError(f'Control {control_id} is missing prose for required section {editable_part.title}')\n\n    # Validate that all required sections are present\n    missing_sections = set(required_sections_list) - set(found_sections)\n    if missing_sections:\n        raise TrestleError(f'Control {control_id} is missing required sections {missing_sections}')\n    param_dict: Dict[str, Any] = {}\n    # get set_params from the header and add to parm_dict\n    header_params = yaml_header.get(const.SET_PARAMS_TAG, {})\n    if header_params:\n        param_dict.update(header_params)\n\n    props, props_by_id = ControlReader.get_props_list(control_id, part_label_to_id_map, yaml_header)\n\n    # When adding props without by_id it can either be starting or ending and we default to ending\n    # This is the default behavior as described for implicit binding in\n    # https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/\n    # When adding props to a part using by_id, it is the same situation because it cannot be before or after since\n    # props are not in the same list as parts\n\n    adds: List[prof.Add] = []\n\n    # add the parts and props at control level\n    if editable_parts or props:\n        adds.append(\n            prof.Add(\n                parts=none_if_empty(editable_parts),\n                props=none_if_empty(props),\n                position=prof.PositionValidValues.ending.value\n            )\n        )\n\n    # add the parts and props at the part level, by-id\n    by_ids = set(by_id_parts.keys()).union(props_by_id.keys())\n    for by_id in sorted(by_ids):\n        parts = by_id_parts.get(by_id, None)\n        props = props_by_id.get(by_id, None)\n        adds.append(prof.Add(parts=parts, props=props, position=prof.PositionValidValues.ending.value, by_id=by_id))\n\n    new_alters = []\n    if adds:\n        new_alters = [prof.Alter(control_id=control_id, adds=adds)]\n    return sort_id, new_alters, param_dict\n
                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_implemented_requirement","title":"read_implemented_requirement(control_file, context) staticmethod","text":"

                                    Get the implementated requirement associated with given control and link to existing components or new ones.

                                    Parameters:

                                    Name Type Description Default control_file Path

                                    path of the control markdown file

                                    required context ControlContext

                                    context of the control usage

                                    required

                                    Returns:

                                    Type Description Tuple

                                    The control sort-id and the one implemented requirement for this control.

                                    Notes

                                    Each statement may have several responses, with each response in a by_component for a specific component. statement_map keeps track of statements that may have several by_component responses. This is only used during component assemble and only for updating one component.

                                    Source code in trestle/core/control_reader.py
                                    @staticmethod\ndef read_implemented_requirement(control_file: pathlib.Path,\n                                 context: ControlContext) -> Tuple[str, comp.ImplementedRequirement]:\n\"\"\"\n    Get the implementated requirement associated with given control and link to existing components or new ones.\n\n    Args:\n        control_file: path of the control markdown file\n        context: context of the control usage\n\n    Returns:\n        Tuple: The control sort-id and the one implemented requirement for this control.\n\n    Notes:\n        Each statement may have several responses, with each response in a by_component for a specific component.\n        statement_map keeps track of statements that may have several by_component responses.\n        This is only used during component assemble and only for updating one component.\n    \"\"\"\n    control_id = control_file.stem\n    md_header, md_comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n    comp_name = context.component.title\n\n    statement_map: Dict[str, comp.Statement] = {}\n    # create a new implemented requirement linked to the control id to hold the statements\n    imp_req = gens.generate_sample_model(comp.ImplementedRequirement)\n    imp_req.control_id = control_id\n\n    imp_req.statements = []\n    comp_dict = md_comp_dict[comp_name]\n    for label, comp_info in comp_dict.items():\n        # only assemble responses with associated rules\n        if not comp_info.rules:\n            continue\n        # if no label it applies to the imp_req itself rather than a statement\n        if not label:\n            imp_req.description = ControlReader._handle_empty_prose(comp_info.prose, control_id)\n            ControlInterface.insert_status_in_props(imp_req, comp_info.status)\n            continue\n        statement_id = ControlInterface.create_statement_id(control_id)\n        if label in ['', const.STATEMENT]:\n            statement_part_id = statement_id\n        else:\n            clean_label = label.strip('.')\n            statement_part_id = ControlInterface.strip_to_make_ncname(f'{statement_id}.{clean_label}')\n        if statement_part_id in statement_map:\n            statement = statement_map[statement_part_id]\n        else:\n            statement = gens.generate_sample_model(comp.Statement)\n            statement.statement_id = statement_part_id\n            statement_map[statement_part_id] = statement\n        statement.description = comp_info.prose\n        statement.props = none_if_empty(ControlInterface.clean_props(comp_info.props))\n        ControlInterface.insert_status_in_props(statement, comp_info.status)\n\n    imp_req.statements = list(statement_map.values())\n    imp_req.set_parameters = []\n\n    for _, param_dict_list in md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {}).items():\n        for param_dict in param_dict_list:\n            values = param_dict.get(const.VALUES, [])\n            comp_values = param_dict.get(const.COMPONENT_VALUES, [])\n            values = comp_values if comp_values else values\n            set_param = ossp.SetParameter(param_id=param_dict['name'], values=values)\n            imp_req.set_parameters.append(set_param)\n    imp_req.statements = none_if_empty(list(statement_map.values()))\n    imp_req.set_parameters = none_if_empty(imp_req.set_parameters)\n\n    ControlReader._insert_header_content(imp_req, md_header, control_id)\n    sort_id = md_header.get(const.SORT_ID, control_id)\n    return sort_id, imp_req\n
                                    "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.simplify_name","title":"simplify_name(name) staticmethod","text":"

                                    Simplify the name to ignore variations in case, space, hyphen, underscore, slash.

                                    Source code in trestle/core/control_reader.py
                                    @staticmethod\ndef simplify_name(name: str) -> str:\n\"\"\"Simplify the name to ignore variations in case, space, hyphen, underscore, slash.\"\"\"\n    return name.lower().replace(' ', '').replace('-', '').replace('_', '').replace('/', '')\n
                                    "},{"location":"api_reference/trestle.core.control_writer/","title":"control_writer","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer","title":"trestle.core.control_writer","text":"

                                    Handle writing of controls to markdown.

                                    "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter","title":" ControlWriter ","text":"

                                    Class to write controls as markdown.

                                    Source code in trestle/core/control_writer.py
                                    class ControlWriter():\n\"\"\"Class to write controls as markdown.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize the class.\"\"\"\n        self._md_file: Optional[MDWriter] = None\n\n    def _add_part_and_its_items(self, control: cat.Control, name: str, item_type: str) -> None:\n\"\"\"For a given control add its one statement and its items to the md file after replacing params.\"\"\"\n        items = []\n        if control.parts:\n            for part in control.parts:\n                if part.name == name:\n                    # If the part has prose write it as a raw line and not list element\n                    skip_id = part.id\n                    if part.prose:\n                        self._md_file.new_line(part.prose)\n                    items.append(ControlInterface.get_part(part, item_type, skip_id))\n            # unwrap the list if it is many levels deep\n            while not isinstance(items, str) and len(items) == 1:\n                items = items[0]\n            self._md_file.new_paragraph()\n            self._md_file.new_list(items)\n\n    def _add_yaml_header(self, yaml_header: Optional[Dict]) -> None:\n        if yaml_header:\n            self._md_file.add_yaml_header(yaml_header)\n\n    def _add_control_statement(self, control: cat.Control, group_title: str, print_group_title=True) -> None:\n\"\"\"Add the control statement and items to the md file.\"\"\"\n        self._md_file.new_paragraph()\n        control_id = control.id\n        group_name = ''\n        control_title = control.title\n\n        if print_group_title:\n            group_name = ' \\[' + group_title + '\\]'\n\n        title = f'{control_id} -{group_name} {control_title}'\n\n        header_title = 'Control Statement'\n        self._md_file.new_header(level=1, title=title)\n        self._md_file.new_header(level=2, title=header_title)\n        self._md_file.set_indent_level(-1)\n        self._add_part_and_its_items(control, const.STATEMENT, const.ITEM)\n        self._md_file.set_indent_level(-1)\n\n    def _add_control_objective(self, control: cat.Control) -> None:\n        if control.parts:\n            for part in control.parts:\n                if part.name == const.OBJECTIVE_PART or part.name == const.ASSESMENT_OBJECTIVE_PART:\n                    self._md_file.new_paragraph()\n                    heading_title = 'Control Objective'\n                    if part.name == const.ASSESMENT_OBJECTIVE_PART:\n                        heading_title = 'Control Assessment Objective'\n                    self._md_file.new_header(level=2, title=heading_title)\n                    self._md_file.set_indent_level(-1)\n                    self._add_part_and_its_items(control, part.name, part.name)\n                    self._md_file.set_indent_level(-1)\n                    return\n\n    def _add_sections(self, control: cat.Control, allowed_sections: Optional[List[str]]) -> None:\n\"\"\"Add the extra control sections after the main ones.\"\"\"\n        skip_section_list = [const.STATEMENT, const.ITEM, const.OBJECTIVE_PART, const.ASSESMENT_OBJECTIVE_PART]\n        while True:\n            _, name, title, prose = ControlInterface.get_section(control, skip_section_list)\n            if not name:\n                return\n            if allowed_sections and name not in allowed_sections:\n                skip_section_list.append(name)\n                continue\n            if prose:\n                # section title will be from the section_dict, the part title, or the part name in that order\n                # this way the user-provided section title can override the part title\n                section_title = self._sections_dict.get(name, title) if self._sections_dict else title\n                section_title = section_title if section_title else name\n                skip_section_list.append(name)\n                self._md_file.new_header(level=2, title=f'Control {section_title}')\n                self._md_file.new_line(prose)\n                self._md_file.new_paragraph()\n\n    def _insert_status(self, status: ImplementationStatus, level: int) -> None:\n        self._md_file.new_header(level=level, title=f'{const.IMPLEMENTATION_STATUS_HEADER}: {status.state}')\n        # this used to output remarks also\n\n    def _insert_rules(self, rules: List[str], level: int) -> None:\n        if rules:\n            self._md_file.new_header(level=level, title='Rules:')\n            self._md_file.set_indent_level(0)\n            self._md_file.new_list(rules)\n            self._md_file.set_indent_level(-1)\n\n    def _insert_comp_info(\n        self, part_label: str, comp_info: Dict[str, ComponentImpInfo], context: ControlContext\n    ) -> None:\n\"\"\"Insert prose and status from the component info.\"\"\"\n        level = 3 if context.purpose == ContextPurpose.COMPONENT else 4\n        if part_label in comp_info:\n            info = comp_info[part_label]\n            if context.purpose in [ContextPurpose.COMPONENT, ContextPurpose.SSP] and not info.rules:\n                return\n            self._md_file.new_paragraph()\n            if info.prose:\n                self._md_file.new_line(info.prose)\n            else:\n                self._md_file.new_line(f'{const.SSP_ADD_IMPLEMENTATION_FOR_ITEM_TEXT} {part_label} -->')\n\n            self._insert_rules(info.rules, level)\n            self._insert_status(info.status, level)\n        else:\n            self._insert_status(ImplementationStatus(state=const.STATUS_PLANNED), level)\n\n    def _add_component_control_prompts(self, control_id: str, comp_dict: CompDict, context: ControlContext) -> bool:\n\"\"\"Add prompts to the markdown for the control itself, per component.\"\"\"\n        if context.purpose not in [ContextPurpose.COMPONENT, ContextPurpose.SSP]:\n            return False\n        self._md_file.new_paraline(const.STATUS_PROMPT)\n        self._md_file.new_paraline(const.RULES_WARNING)\n        did_write = False\n        # do special handling for This System\n        if context.purpose == ContextPurpose.SSP:\n            self._md_file.new_paragraph()\n            self._md_file.new_header(3, const.SSP_MAIN_COMP_NAME)\n            self._md_file.new_paragraph()\n            prose = f'{const.SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT}: {control_id} -->'\n            status = ImplementationStatus(state=const.STATUS_PLANNED)\n            if const.SSP_MAIN_COMP_NAME in comp_dict:\n                comp_info = list(comp_dict[const.SSP_MAIN_COMP_NAME].values())[0]\n                if comp_info.prose:\n                    prose = comp_info.prose\n                status = comp_info.status\n            self._md_file.new_paraline(prose)\n            self._insert_status(status, 4)\n            did_write = True\n        sorted_comp_names = sorted(comp_dict.keys())\n        for comp_name in sorted_comp_names:\n            dic = comp_dict[comp_name]\n            # This System already handled\n            if comp_name == const.SSP_MAIN_COMP_NAME:\n                continue\n            for comp_info in [val for key, val in dic.items() if key == '']:\n                # don't output component name for component markdown since only one component\n                if context.purpose != ContextPurpose.COMPONENT:\n                    self._md_file.new_header(3, comp_name)\n                prose = comp_info.prose if comp_info.prose != control_id else ''\n                if not prose:\n                    prose = f'{const.SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT}: {control_id} -->'\n                self._md_file.new_paraline(prose)\n                level = 3 if context.purpose == ContextPurpose.COMPONENT else 4\n                self._insert_rules(comp_info.rules, level)\n                self._insert_status(comp_info.status, level)\n                did_write = True\n        return did_write\n\n    def _add_implementation_response_prompts(\n        self, control: cat.Control, comp_dict: CompDict, context: ControlContext\n    ) -> None:\n\"\"\"Add the response request text for all parts to the markdown along with the header.\"\"\"\n        self._md_file.new_hr()\n        self._md_file.new_paragraph()\n        # top level request for implementation details\n        self._md_file.new_header(level=2, title=f'{const.SSP_MD_IMPLEMENTATION_QUESTION}')\n\n        # write out control level prose and status\n        did_write_part = self._add_component_control_prompts(control.id, comp_dict, context)\n\n        # if the control has no parts written out then enter implementation in the top level entry\n        # but if it does have parts written out, leave top level blank and provide details in the parts\n        # Note that parts corresponding to sections don't get written out here so a check is needed\n        # If we have responses per component then enter them in separate ### sections\n        if control.parts:\n            for part in control.parts:\n                if part.parts and part.name == const.STATEMENT:\n                    for prt in part.parts:\n                        if prt.name != const.ITEM:\n                            continue\n                        # if no label guess the label from the sub-part id\n                        part_label = ControlInterface.get_label(prt)\n                        part_label = prt.id.split('.')[-1] if not part_label else part_label\n                        # only write out part if rules apply to it\n                        rules_apply = False\n                        for _, dic in comp_dict.items():\n                            if part_label in dic and dic[part_label].rules:\n                                rules_apply = True\n                                break\n                        if not rules_apply:\n                            continue\n                        if not did_write_part:\n                            self._md_file.new_line(const.SSP_MD_LEAVE_BLANK_TEXT)\n                            # insert extra line to make mdformat happy\n                            self._md_file._add_line_raw('')\n                        self._md_file.new_hr()\n                        self._md_file.new_header(level=2, title=f'Implementation for part {part_label}')\n                        wrote_label_content = False\n                        sorted_comp_names = sorted(comp_dict.keys())\n                        for comp_name in sorted_comp_names:\n                            dic = comp_dict[comp_name]\n                            if comp_name == const.SSP_MAIN_COMP_NAME:\n                                continue\n                            if part_label in dic:\n                                # insert the component name for ssp but not for comp_def\n                                # because there should only be one component in generated comp_def markdown\n                                if context.purpose != ContextPurpose.COMPONENT:\n                                    self._md_file.new_header(level=3, title=comp_name)\n                                self._insert_comp_info(part_label, dic, context)\n                                wrote_label_content = True\n                        if not wrote_label_content:\n                            level = 3 if context.purpose == ContextPurpose.COMPONENT else 4\n                            self._insert_status(ImplementationStatus(state=const.STATUS_PLANNED), level)\n                        self._md_file.new_paragraph()\n                        did_write_part = True\n        # if we loaded nothing for this control yet then it must need a fresh prompt for the control statement\n        if not comp_dict and not did_write_part:\n            self._md_file.new_line(f'{const.SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT}: {control.id} -->')\n            if context.purpose in [ContextPurpose.COMPONENT, ContextPurpose.SSP]:\n                status = ControlInterface.get_status_from_props(control)\n                self._insert_status(status, 3)\n        if not did_write_part:\n            part_label = ''\n            for comp_name, dic in comp_dict.items():\n                if part_label in dic:\n                    if comp_name != const.SSP_MAIN_COMP_NAME:\n                        self._md_file.new_header(level=3, title=comp_name)\n                    self._insert_comp_info(part_label, dic, context)\n        self._md_file.new_hr()\n\n    def _dump_subpart_infos(self, level: int, part: Dict[str, Any]) -> None:\n        name = part['name']\n        title = self._sections_dict.get(name, name) if self._sections_dict else name\n        self._md_file.new_header(level=level, title=title)\n        if 'prose' in part:\n            self._md_file.new_paraline(part['prose'])\n        for subpart in as_list(part.get('parts', None)):\n            self._dump_subpart_infos(level + 1, subpart)\n\n    def _dump_subparts(self, level: int, part: Part) -> None:\n        name = part.name\n        title = self._sections_dict.get(name, name) if self._sections_dict else name\n        self._md_file.new_header(level=level, title=title)\n        if part.prose:\n            self._md_file.new_paraline(part.prose)\n        for subpart in as_list(part.parts):\n            self._dump_subparts(level + 1, subpart)\n\n    def _dump_section(self, level: int, part: Part, added_sections: List[str], prefix: str) -> None:\n        title = self._sections_dict.get(part.name, part.name) if self._sections_dict else part.name\n        title = f'{prefix} {title}' if prefix else title\n        self._md_file.new_header(level=level, title=title)\n        if part.prose:\n            self._md_file.new_paraline(part.prose)\n        for subpart in as_list(part.parts):\n            self._dump_subparts(level + 1, subpart)\n        added_sections.append(part.name)\n\n    def _dump_section_info(self, level: int, part: Dict[str, Any], added_sections: List[str], prefix: str) -> None:\n        part_prose = part.get('prose', None)\n        part_subparts = part.get('parts', None)\n        name = part['name']\n        title = self._sections_dict.get(name, name) if self._sections_dict else name\n        title = f'{prefix} {title}' if prefix else title\n        self._md_file.new_header(level=level, title=title)\n        if part_prose:\n            self._md_file.new_paraline(part_prose)\n        for subpart in as_list(part_subparts):\n            self._dump_subpart_infos(level + 1, subpart)\n        added_sections.append(name)\n\n    def _add_additional_content(\n        self,\n        control: cat.Control,\n        profile: prof.Profile,\n        header: Dict[str, Any],\n        part_id_map: Dict[str, str],\n        found_alters: List[prof.Alter]\n    ) -> List[str]:\n        # get part and subpart info from adds of the profile\n        part_infos = ControlInterface.get_all_add_info(control.id, profile)\n        has_content = len(part_infos) > 0\n\n        self._md_file.new_header(level=1, title=const.EDITABLE_CONTENT)\n        self._md_file.new_line('<!-- Make additions and edits below -->')\n        self._md_file.new_line(\n            '<!-- The above represents the contents of the control as received by the profile, prior to additions. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- If the profile makes additions to the control, they will appear below. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- The above markdown may not be edited but you may edit the content below, and/or introduce new additions to be made by the profile. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- If there is a yaml header at the top, parameter values may be edited. Use --set-parameters to incorporate the changes during assembly. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- The content here will then replace what is in the profile for this control, after running profile-assemble. -->'  # noqa E501\n        )\n        if has_content:\n            self._md_file.new_line(\n                '<!-- The added parts in the profile for this control are below.  You may edit them and/or add new ones. -->'  # noqa E501\n            )\n        else:\n            self._md_file.new_line(\n                '<!-- The current profile has no added parts for this control, but you may add new ones here. -->'\n            )\n        self._md_file.new_line(\n            '<!-- Each addition must have a heading either of the form ## Control my_addition_name -->'\n        )\n        self._md_file.new_line('<!-- or ## Part a. (where the a. refers to one of the control statement labels.) -->')\n        self._md_file.new_line('<!-- \"## Control\" parts are new parts added after the statement part. -->')\n        self._md_file.new_line(\n            '<!-- \"## Part\" parts are new parts added into the top-level statement part with that label. -->'\n        )\n        self._md_file.new_line('<!-- Subparts may be added with nested hash levels of the form ### My Subpart Name -->')\n        self._md_file.new_line('<!-- underneath the parent ## Control or ## Part being added -->')\n        self._md_file.new_line(\n            '<!-- See https://oscal-compass.github.io/compliance-trestle/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring for guidance. -->'  # noqa E501\n        )\n        # next is to make mdformat happy\n        self._md_file._add_line_raw('')\n\n        added_sections: List[str] = []\n\n        control_part_id_map = part_id_map.get(control.id, {})\n        statement_id = ControlInterface.get_statement_id(control)\n\n        # if the file already has markdown content, read its alters\n        if self._md_file.exists():\n            if const.TRESTLE_ADD_PROPS_TAG in header:\n                header.pop(const.TRESTLE_ADD_PROPS_TAG)\n            for alter in found_alters:\n                for add in as_list(alter.adds):\n                    # by_id could refer to statement (Control) or part (Part)\n                    if add.by_id:\n                        # is this a part that goes after the control statement\n                        if add.by_id == statement_id:\n                            for part in as_list(add.parts):\n                                if part.prose or part.parts:\n                                    self._dump_section(2, part, added_sections, 'Control')\n                        else:\n                            # or is it a sub-part of a statement part\n                            part_label = control_part_id_map.get(add.by_id, add.by_id)\n                            if add.parts:\n                                self._md_file.new_header(level=2, title=f'Part {part_label}')\n                                for part in as_list(add.parts):\n                                    if part.prose or part.parts:\n                                        name = part.name\n                                        # need special handling for statement parts because their name is 'item'\n                                        # get the short name as last piece of the part id after the '.'\n                                        if name == const.ITEM:\n                                            name = part.id.split('.')[-1]\n                                        title = self._sections_dict.get(name, name) if self._sections_dict else name\n                                        self._md_file.new_header(level=3, title=title)\n                                        if part.prose:\n                                            self._md_file.new_paraline(part.prose)\n                                        for subpart in as_list(part.parts):\n                                            self._dump_subparts(3, subpart)\n                                        added_sections.append(name)\n                    else:\n                        # if not by_id just add at end of control's parts\n                        for part in as_list(add.parts):\n                            if part.prose or part.parts:\n                                self._dump_section(2, part, added_sections, 'Control')\n                    if add.props:\n                        if const.TRESTLE_ADD_PROPS_TAG not in header:\n                            header[const.TRESTLE_ADD_PROPS_TAG] = []\n                        by_id = add.by_id\n                        part_info = PartInfo(name='', prose='', props=add.props, smt_part=by_id)\n                        _, prop_list = part_info.to_dicts(part_id_map.get(control.id, {}))\n                        header[const.TRESTLE_ADD_PROPS_TAG].extend(prop_list)\n        else:\n            # md does not already exist so fill in directly\n            in_part = ''\n            for part_info in part_infos:\n                part, prop_list = part_info.to_dicts(part_id_map.get(control.id, {}))\n                # is this part of a statement part\n                if part_info.smt_part and part_info.prose and part_info.smt_part in control_part_id_map:\n                    # avoid outputting ## Part again if in same part\n                    if not part_info.smt_part == in_part:\n                        in_part = part_info.smt_part\n                        part_label = control_part_id_map.get(part_info.smt_part, part_info.smt_part)\n                        self._md_file.new_header(level=2, title=f'Part {part_label}')\n                    self._dump_section_info(3, part, added_sections, '')\n                # is it a control part\n                elif part_info.prose or part_info.parts:\n                    in_part = ''\n                    self._dump_section_info(2, part, added_sections, 'Control')\n                elif prop_list:\n                    in_part = ''\n                    if const.TRESTLE_ADD_PROPS_TAG not in header:\n                        header[const.TRESTLE_ADD_PROPS_TAG] = []\n                    header[const.TRESTLE_ADD_PROPS_TAG].extend(prop_list)\n        return added_sections\n\n    def _prompt_required_sections(self, required_sections: List[str], added_sections: List[str]) -> None:\n\"\"\"Add prompts for any required sections that haven't already been written out.\"\"\"\n        missing_sections = set(required_sections).difference(added_sections)\n        for section in sorted(missing_sections):\n            section_title = self._sections_dict.get(section, section)\n            self._md_file.new_header(2, f'Control {section_title}')\n            self._md_file.new_line(f'{const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT}: {section_title} -->')\n\n    @staticmethod\n    def _merge_headers(memory_header: Dict[str, Any], md_header: Dict[str, Any],\n                       context: ControlContext) -> Dict[str, Any]:\n        merged_header = copy.deepcopy(md_header)\n        ControlInterface.merge_dicts_deep(merged_header, memory_header, False, 1)\n        return merged_header\n\n    def write_control_for_editing(\n        self,\n        context: ControlContext,\n        control: cat.Control,\n        dest_path: pathlib.Path,\n        group_title: str,\n        part_id_map: Dict[str, str],\n        found_alters: List[prof.Alter]\n    ) -> None:\n\"\"\"\n        Write out the control in markdown format into the specified directory.\n\n        Args:\n            context: The context of the control usage\n            control: The control to write as markdown\n            dest_path: Path to the directory where the control will be written\n            group_title: Title of the group containing the control\n            part_id_map: Mapping of part_id to label\n            found_alters: List of alters read from the markdown file - if it exists\n\n        Returns:\n            None\n\n        Notes:\n            The filename is constructed from the control's id and created in the dest_path.\n            If a yaml header is present in the file, new values in provided header will not replace those in the\n            markdown header unless overwrite_header_values is true.  If it is true then overwrite any existing values,\n            but in all cases new items from the provided header will be added to the markdown header.\n            If the markdown file already exists, its current header and prose are read.\n            Controls are checked if they are marked withdrawn, and if so they are not written out.\n        \"\"\"\n        if ControlInterface.is_withdrawn(control):\n            logger.debug(f'Not writing out control {control.id} since it is marked Withdrawn.')\n            return\n\n        control_file = dest_path / (control.id + const.MARKDOWN_FILE_EXT)\n        # read the existing markdown header and content if it exists\n        md_header, comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n        # replace the memory comp_dict with the md one if control exists\n        if comp_dict:\n            context.comp_dict = comp_dict\n\n        header_comment_dict = {const.TRESTLE_ADD_PROPS_TAG: const.YAML_PROPS_COMMENT}\n        if context.to_markdown:\n            if context.purpose == ContextPurpose.PROFILE:\n                header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_PROFILE_VALUES_COMMENT\n            elif context.purpose == ContextPurpose.SSP:\n                header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_SSP_VALUES_COMMENT\n                header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG] = const.YAML_RULE_PARAM_VALUES_SSP_COMMENT\n                # The add props information to SSP only. It is added to the profile later.\n                if const.TRESTLE_ADD_PROPS_TAG not in md_header:\n                    md_header[const.TRESTLE_ADD_PROPS_TAG] = []\n            elif context.purpose == ContextPurpose.COMPONENT:\n                header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG\n                                    ] = const.YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT\n\n        # begin adding info to the md file\n        self._md_file = MDWriter(control_file, header_comment_dict)\n        self._sections_dict = context.sections_dict\n\n        context.merged_header = ControlWriter._merge_headers(context.merged_header, md_header, context)\n        # if the control has an explicitly defined sort-id and there is none in the yaml_header, then insert it\n        # in the yaml header and allow overwrite_header_values to control whether it overwrites an existing one\n        # in the markdown header\n        context.cli_yaml_header = as_dict(context.cli_yaml_header)\n        if context.purpose != ContextPurpose.PROFILE:\n            ControlInterface.merge_dicts_deep(\n                context.merged_header, context.cli_yaml_header, context.overwrite_header_values\n            )\n        # the global contents are special and get overwritten on generate\n        set_or_pop(\n            context.merged_header,\n            const.TRESTLE_GLOBAL_TAG,\n            context.cli_yaml_header.get(const.TRESTLE_GLOBAL_TAG, None)\n        )\n        sort_id = ControlInterface.get_sort_id(control, True)\n        if sort_id:\n            deep_set(context.merged_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], sort_id)\n\n        # merge any provided sections with sections in the header, with priority to the one from context (e.g. CLI)\n        header_sections_dict = context.merged_header.get(const.SECTIONS_TAG, {})\n        merged_sections_dict = merge_dicts(header_sections_dict, context.sections_dict)\n        set_or_pop(context.merged_header, const.SECTIONS_TAG, merged_sections_dict)\n\n        # now begin filling in content from the control in memory\n        self._add_control_statement(control, group_title)\n\n        self._add_control_objective(control)\n\n        # add allowed sections to the markdown\n        self._add_sections(control, context.allowed_sections)\n\n        # prompt responses for imp reqs using special format if comp_def mode\n        if context.prompt_responses:\n            self._add_implementation_response_prompts(control, context.comp_dict, context)\n\n        # for profile generate\n        # add sections corresponding to added parts in the profile\n        added_sections: List[str] = []\n        if context.purpose == ContextPurpose.PROFILE:\n            added_sections = self._add_additional_content(\n                control, context.profile, context.merged_header, part_id_map, found_alters\n            )\n\n        self._add_yaml_header(context.merged_header)\n\n        if context.required_sections:\n            self._prompt_required_sections(context.required_sections, added_sections)\n\n        self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter.__init__","title":"__init__(self) special","text":"

                                    Initialize the class.

                                    Source code in trestle/core/control_writer.py
                                    def __init__(self):\n\"\"\"Initialize the class.\"\"\"\n    self._md_file: Optional[MDWriter] = None\n
                                    "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter.write_control_for_editing","title":"write_control_for_editing(self, context, control, dest_path, group_title, part_id_map, found_alters)","text":"

                                    Write out the control in markdown format into the specified directory.

                                    Parameters:

                                    Name Type Description Default context ControlContext

                                    The context of the control usage

                                    required control Control

                                    The control to write as markdown

                                    required dest_path Path

                                    Path to the directory where the control will be written

                                    required group_title str

                                    Title of the group containing the control

                                    required part_id_map Dict[str, str]

                                    Mapping of part_id to label

                                    required found_alters List[trestle.oscal.profile.Alter]

                                    List of alters read from the markdown file - if it exists

                                    required

                                    Returns:

                                    Type Description None

                                    None

                                    Notes

                                    The filename is constructed from the control's id and created in the dest_path. If a yaml header is present in the file, new values in provided header will not replace those in the markdown header unless overwrite_header_values is true. If it is true then overwrite any existing values, but in all cases new items from the provided header will be added to the markdown header. If the markdown file already exists, its current header and prose are read. Controls are checked if they are marked withdrawn, and if so they are not written out.

                                    Source code in trestle/core/control_writer.py
                                    def write_control_for_editing(\n    self,\n    context: ControlContext,\n    control: cat.Control,\n    dest_path: pathlib.Path,\n    group_title: str,\n    part_id_map: Dict[str, str],\n    found_alters: List[prof.Alter]\n) -> None:\n\"\"\"\n    Write out the control in markdown format into the specified directory.\n\n    Args:\n        context: The context of the control usage\n        control: The control to write as markdown\n        dest_path: Path to the directory where the control will be written\n        group_title: Title of the group containing the control\n        part_id_map: Mapping of part_id to label\n        found_alters: List of alters read from the markdown file - if it exists\n\n    Returns:\n        None\n\n    Notes:\n        The filename is constructed from the control's id and created in the dest_path.\n        If a yaml header is present in the file, new values in provided header will not replace those in the\n        markdown header unless overwrite_header_values is true.  If it is true then overwrite any existing values,\n        but in all cases new items from the provided header will be added to the markdown header.\n        If the markdown file already exists, its current header and prose are read.\n        Controls are checked if they are marked withdrawn, and if so they are not written out.\n    \"\"\"\n    if ControlInterface.is_withdrawn(control):\n        logger.debug(f'Not writing out control {control.id} since it is marked Withdrawn.')\n        return\n\n    control_file = dest_path / (control.id + const.MARKDOWN_FILE_EXT)\n    # read the existing markdown header and content if it exists\n    md_header, comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n    # replace the memory comp_dict with the md one if control exists\n    if comp_dict:\n        context.comp_dict = comp_dict\n\n    header_comment_dict = {const.TRESTLE_ADD_PROPS_TAG: const.YAML_PROPS_COMMENT}\n    if context.to_markdown:\n        if context.purpose == ContextPurpose.PROFILE:\n            header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_PROFILE_VALUES_COMMENT\n        elif context.purpose == ContextPurpose.SSP:\n            header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_SSP_VALUES_COMMENT\n            header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG] = const.YAML_RULE_PARAM_VALUES_SSP_COMMENT\n            # The add props information to SSP only. It is added to the profile later.\n            if const.TRESTLE_ADD_PROPS_TAG not in md_header:\n                md_header[const.TRESTLE_ADD_PROPS_TAG] = []\n        elif context.purpose == ContextPurpose.COMPONENT:\n            header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG\n                                ] = const.YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT\n\n    # begin adding info to the md file\n    self._md_file = MDWriter(control_file, header_comment_dict)\n    self._sections_dict = context.sections_dict\n\n    context.merged_header = ControlWriter._merge_headers(context.merged_header, md_header, context)\n    # if the control has an explicitly defined sort-id and there is none in the yaml_header, then insert it\n    # in the yaml header and allow overwrite_header_values to control whether it overwrites an existing one\n    # in the markdown header\n    context.cli_yaml_header = as_dict(context.cli_yaml_header)\n    if context.purpose != ContextPurpose.PROFILE:\n        ControlInterface.merge_dicts_deep(\n            context.merged_header, context.cli_yaml_header, context.overwrite_header_values\n        )\n    # the global contents are special and get overwritten on generate\n    set_or_pop(\n        context.merged_header,\n        const.TRESTLE_GLOBAL_TAG,\n        context.cli_yaml_header.get(const.TRESTLE_GLOBAL_TAG, None)\n    )\n    sort_id = ControlInterface.get_sort_id(control, True)\n    if sort_id:\n        deep_set(context.merged_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], sort_id)\n\n    # merge any provided sections with sections in the header, with priority to the one from context (e.g. CLI)\n    header_sections_dict = context.merged_header.get(const.SECTIONS_TAG, {})\n    merged_sections_dict = merge_dicts(header_sections_dict, context.sections_dict)\n    set_or_pop(context.merged_header, const.SECTIONS_TAG, merged_sections_dict)\n\n    # now begin filling in content from the control in memory\n    self._add_control_statement(control, group_title)\n\n    self._add_control_objective(control)\n\n    # add allowed sections to the markdown\n    self._add_sections(control, context.allowed_sections)\n\n    # prompt responses for imp reqs using special format if comp_def mode\n    if context.prompt_responses:\n        self._add_implementation_response_prompts(control, context.comp_dict, context)\n\n    # for profile generate\n    # add sections corresponding to added parts in the profile\n    added_sections: List[str] = []\n    if context.purpose == ContextPurpose.PROFILE:\n        added_sections = self._add_additional_content(\n            control, context.profile, context.merged_header, part_id_map, found_alters\n        )\n\n    self._add_yaml_header(context.merged_header)\n\n    if context.required_sections:\n        self._prompt_required_sections(context.required_sections, added_sections)\n\n    self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/","title":"bycomp_interface","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface","title":"trestle.core.crm.bycomp_interface","text":"

                                    Provide interface to by-component allowing queries and operations for exports/inheritance statements.

                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface","title":" ByComponentInterface ","text":"

                                    Interface to query and modify by-component assembly inheritance contents.

                                    The by-component is contained in two separate forms: As an actual OSCAL by-component assembly, and multiple dicts providing direct lookup of inheritance statement by uuid.

                                    The dicts are created by the ByComponentInterface constructor, parsed and the responsibility and provided statements are separated into three catagories:

                                    isolated responsibilities - A responsibility with no provided statement isolated provided - A provided statement with no referring responsibility statements export set - A set with a single responsibility and referred provided statement

                                    For updating ByComponent inheritance and satisfied statements, the interface provides a method to reconcile the the by-component assembly and merge input inherited and satisfied statements.

                                    Source code in trestle/core/crm/bycomp_interface.py
                                    class ByComponentInterface:\n\"\"\"\n    Interface to query and modify by-component assembly inheritance contents.\n\n    The by-component is contained in two separate forms:  As an actual OSCAL by-component assembly,\n    and multiple dicts providing direct lookup of inheritance statement by uuid.\n\n    The dicts are created by the ByComponentInterface constructor, parsed and the responsibility and provided statements\n    are separated into three catagories:\n\n    isolated responsibilities - A responsibility with no provided statement\n    isolated provided - A provided statement with no referring responsibility statements\n    export set - A set with a single responsibility and referred provided statement\n\n    For updating ByComponent inheritance and satisfied statements, the interface provides a method to reconcile the\n    the by-component assembly and merge input inherited and satisfied statements.\n    \"\"\"\n\n    def __init__(self, by_comp: ossp.ByComponent):\n\"\"\"Initialize export writer for a single by-component assembly.\"\"\"\n        self._by_comp: ossp.ByComponent = by_comp\n\n        self._provided_dict: Dict[str, ossp.Provided] = {}\n        self._responsibility_dict: Dict[str, ossp.Responsibility] = {}\n        self._responsibility_by_provided: Dict[str, List[ossp.Responsibility]] = {}\n\n        self._inherited_dict: Dict[str, ossp.Inherited] = self._create_inherited_dict()\n        self._satisfied_dict: Dict[str, ossp.Satisfied] = self._create_satisfied_dict()\n\n        if by_comp.export:\n            self._provided_dict = self._create_provided_dict()\n            self._responsibility_dict = self._create_responsibility_dict()\n            self._responsibility_by_provided = self._create_responsibility_by_provided_dict()\n\n    def _create_provided_dict(self) -> Dict[str, ossp.Provided]:\n        provided_dict: Dict[str, ossp.Provided] = {}\n        for provided in as_list(self._by_comp.export.provided):\n            provided_dict[provided.uuid] = provided\n        return provided_dict\n\n    def _create_responsibility_dict(self) -> Dict[str, ossp.Responsibility]:\n        responsibility_dict: Dict[str, ossp.Responsibility] = {}\n        for responsibility in as_list(self._by_comp.export.responsibilities):\n            responsibility_dict[responsibility.uuid] = responsibility\n        return responsibility_dict\n\n    def _create_responsibility_by_provided_dict(self) -> Dict[str, List[ossp.Responsibility]]:\n        responsibility_by_provided: Dict[str, List[ossp.Responsibility]] = {}\n        for responsibility in as_list(self._by_comp.export.responsibilities):\n            if responsibility.provided_uuid is None:\n                continue\n            if responsibility.provided_uuid not in responsibility_by_provided:\n                responsibility_by_provided[responsibility.provided_uuid] = [responsibility]\n            else:\n                existing_list: List[ossp.Responsibility] = responsibility_by_provided[responsibility.provided_uuid]\n                existing_list.append(responsibility)\n        return responsibility_by_provided\n\n    def _create_inherited_dict(self) -> Dict[str, ossp.Inherited]:\n        inherited_dict: Dict[str, ossp.Inherited] = {}\n        for inherited in as_list(self._by_comp.inherited):\n            inherited_dict[str(inherited.provided_uuid)] = inherited\n        return inherited_dict\n\n    def _create_satisfied_dict(self) -> Dict[str, ossp.Satisfied]:\n        satisfied_dict: Dict[str, ossp.Satisfied] = {}\n        for satisfied in as_list(self._by_comp.satisfied):\n            satisfied_dict[str(satisfied.responsibility_uuid)] = satisfied\n        return satisfied_dict\n\n    def get_isolated_responsibilities(self) -> List[ossp.Responsibility]:\n\"\"\"Return all isolated exported responsibilities.\"\"\"\n        all_responsibilities: List[ossp.Responsibility] = []\n        for resp in as_dict(self._responsibility_dict).values():\n            if resp.provided_uuid is None:\n                all_responsibilities.append(resp)\n        return all_responsibilities\n\n    def get_isolated_provided(self) -> List[ossp.Provided]:\n\"\"\"Return all isolated exported provided capabilities.\"\"\"\n        all_provided: List[ossp.Provided] = []\n        for provided in as_dict(self._provided_dict).values():\n            if not self._provided_has_responsibilities(provided.uuid):\n                all_provided.append(provided)\n        return all_provided\n\n    def get_export_sets(self) -> List[Tuple[ossp.Responsibility, ossp.Provided]]:\n\"\"\"Return a dictionary of every responsibility relationship with provided.\"\"\"\n        all_export_sets: List[Tuple[ossp.Responsibility, ossp.Provided]] = []\n        for provided_uuid, responsibilities in as_dict(self._responsibility_by_provided).items():\n\n            # Ensure the provided object exists in the dictionary.\n            # If it doesn't this is a bug.\n            if provided_uuid not in self._provided_dict:\n                raise TrestleError(f'Provided capability {provided_uuid} not found')\n            provided: ossp.Provided = self._provided_dict[provided_uuid]\n\n            for responsibility in responsibilities:\n                shared_responsibility: Tuple[ossp.Responsibility, ossp.Provided] = (responsibility, provided)\n                all_export_sets.append(shared_responsibility)\n        return all_export_sets\n\n    def reconcile_inheritance_by_component(\n        self, incoming_inherited: List[ossp.Inherited], incoming_satisfied: List[ossp.Satisfied]\n    ) -> ossp.ByComponent:\n\"\"\"\n        Reconcile the inherited and satisfied statements in the by-component assembly with changes from the export.\n\n        Notes:\n            A statement is determined as existing if the provided uuid or responsibility uuid is in the existing\n            by-component assembly. If existing, the description will be updated if it has changed.\n\n            Any existing inherited or satisfied statements that are not in the incoming export will be removed.\n            If a statement is in the incoming export, but not in the existing by-component assembly, it will be added.\n        \"\"\"\n        new_inherited: List[ossp.Inherited] = []\n        new_satisfied: List[ossp.Satisfied] = []\n\n        # Create a copy of the input by-component assembly to reconcile and return\n        new_by_comp: ossp.ByComponent = copy.deepcopy(self._by_comp)\n\n        for statement in incoming_inherited:\n            if statement.provided_uuid in self._inherited_dict:\n                existing_statement = self._inherited_dict[str(statement.provided_uuid)]\n                # Update the description if it has changed\n                existing_statement.description = statement.description\n                statement = existing_statement\n            new_inherited.append(statement)\n\n        new_by_comp.inherited = none_if_empty(new_inherited)\n\n        for statement in incoming_satisfied:\n            if statement.responsibility_uuid in self._satisfied_dict:\n                existing_statement = self._satisfied_dict[str(statement.responsibility_uuid)]\n                # Update the description if it has changed\n                existing_statement.description = statement.description\n                statement = existing_statement\n            new_satisfied.append(statement)\n\n        new_by_comp.satisfied = none_if_empty(new_satisfied)\n\n        return new_by_comp\n\n    def _provided_has_responsibilities(self, provided_uuid: str) -> bool:\n\"\"\"Return whether a provided UUID has responsibilities.\"\"\"\n        return provided_uuid in self._responsibility_by_provided\n
                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.__init__","title":"__init__(self, by_comp) special","text":"

                                    Initialize export writer for a single by-component assembly.

                                    Source code in trestle/core/crm/bycomp_interface.py
                                    def __init__(self, by_comp: ossp.ByComponent):\n\"\"\"Initialize export writer for a single by-component assembly.\"\"\"\n    self._by_comp: ossp.ByComponent = by_comp\n\n    self._provided_dict: Dict[str, ossp.Provided] = {}\n    self._responsibility_dict: Dict[str, ossp.Responsibility] = {}\n    self._responsibility_by_provided: Dict[str, List[ossp.Responsibility]] = {}\n\n    self._inherited_dict: Dict[str, ossp.Inherited] = self._create_inherited_dict()\n    self._satisfied_dict: Dict[str, ossp.Satisfied] = self._create_satisfied_dict()\n\n    if by_comp.export:\n        self._provided_dict = self._create_provided_dict()\n        self._responsibility_dict = self._create_responsibility_dict()\n        self._responsibility_by_provided = self._create_responsibility_by_provided_dict()\n
                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.get_export_sets","title":"get_export_sets(self)","text":"

                                    Return a dictionary of every responsibility relationship with provided.

                                    Source code in trestle/core/crm/bycomp_interface.py
                                    def get_export_sets(self) -> List[Tuple[ossp.Responsibility, ossp.Provided]]:\n\"\"\"Return a dictionary of every responsibility relationship with provided.\"\"\"\n    all_export_sets: List[Tuple[ossp.Responsibility, ossp.Provided]] = []\n    for provided_uuid, responsibilities in as_dict(self._responsibility_by_provided).items():\n\n        # Ensure the provided object exists in the dictionary.\n        # If it doesn't this is a bug.\n        if provided_uuid not in self._provided_dict:\n            raise TrestleError(f'Provided capability {provided_uuid} not found')\n        provided: ossp.Provided = self._provided_dict[provided_uuid]\n\n        for responsibility in responsibilities:\n            shared_responsibility: Tuple[ossp.Responsibility, ossp.Provided] = (responsibility, provided)\n            all_export_sets.append(shared_responsibility)\n    return all_export_sets\n
                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.get_isolated_provided","title":"get_isolated_provided(self)","text":"

                                    Return all isolated exported provided capabilities.

                                    Source code in trestle/core/crm/bycomp_interface.py
                                    def get_isolated_provided(self) -> List[ossp.Provided]:\n\"\"\"Return all isolated exported provided capabilities.\"\"\"\n    all_provided: List[ossp.Provided] = []\n    for provided in as_dict(self._provided_dict).values():\n        if not self._provided_has_responsibilities(provided.uuid):\n            all_provided.append(provided)\n    return all_provided\n
                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.get_isolated_responsibilities","title":"get_isolated_responsibilities(self)","text":"

                                    Return all isolated exported responsibilities.

                                    Source code in trestle/core/crm/bycomp_interface.py
                                    def get_isolated_responsibilities(self) -> List[ossp.Responsibility]:\n\"\"\"Return all isolated exported responsibilities.\"\"\"\n    all_responsibilities: List[ossp.Responsibility] = []\n    for resp in as_dict(self._responsibility_dict).values():\n        if resp.provided_uuid is None:\n            all_responsibilities.append(resp)\n    return all_responsibilities\n
                                    "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.reconcile_inheritance_by_component","title":"reconcile_inheritance_by_component(self, incoming_inherited, incoming_satisfied)","text":"

                                    Reconcile the inherited and satisfied statements in the by-component assembly with changes from the export.

                                    Notes

                                    A statement is determined as existing if the provided uuid or responsibility uuid is in the existing by-component assembly. If existing, the description will be updated if it has changed.

                                    Any existing inherited or satisfied statements that are not in the incoming export will be removed. If a statement is in the incoming export, but not in the existing by-component assembly, it will be added.

                                    Source code in trestle/core/crm/bycomp_interface.py
                                    def reconcile_inheritance_by_component(\n    self, incoming_inherited: List[ossp.Inherited], incoming_satisfied: List[ossp.Satisfied]\n) -> ossp.ByComponent:\n\"\"\"\n    Reconcile the inherited and satisfied statements in the by-component assembly with changes from the export.\n\n    Notes:\n        A statement is determined as existing if the provided uuid or responsibility uuid is in the existing\n        by-component assembly. If existing, the description will be updated if it has changed.\n\n        Any existing inherited or satisfied statements that are not in the incoming export will be removed.\n        If a statement is in the incoming export, but not in the existing by-component assembly, it will be added.\n    \"\"\"\n    new_inherited: List[ossp.Inherited] = []\n    new_satisfied: List[ossp.Satisfied] = []\n\n    # Create a copy of the input by-component assembly to reconcile and return\n    new_by_comp: ossp.ByComponent = copy.deepcopy(self._by_comp)\n\n    for statement in incoming_inherited:\n        if statement.provided_uuid in self._inherited_dict:\n            existing_statement = self._inherited_dict[str(statement.provided_uuid)]\n            # Update the description if it has changed\n            existing_statement.description = statement.description\n            statement = existing_statement\n        new_inherited.append(statement)\n\n    new_by_comp.inherited = none_if_empty(new_inherited)\n\n    for statement in incoming_satisfied:\n        if statement.responsibility_uuid in self._satisfied_dict:\n            existing_statement = self._satisfied_dict[str(statement.responsibility_uuid)]\n            # Update the description if it has changed\n            existing_statement.description = statement.description\n            statement = existing_statement\n        new_satisfied.append(statement)\n\n    new_by_comp.satisfied = none_if_empty(new_satisfied)\n\n    return new_by_comp\n
                                    "},{"location":"api_reference/trestle.core.crm.export_reader/","title":"export_reader","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader","title":"trestle.core.crm.export_reader","text":"

                                    Provided interface to read inheritance statements from Markdown.

                                    "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ByComponentDict","title":"ByComponentDict","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.InheritanceViewDict","title":"InheritanceViewDict","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader","title":" ExportReader ","text":"

                                    By-Component Assembly Exports Markdown reader.

                                    Export reader handles all operations related to reading authored inherited and satisfied statements from exports in Markdown. The reader will read all the markdown files in the exports directory and update the SSP with the inheritance.

                                    Source code in trestle/core/crm/export_reader.py
                                    class ExportReader:\n\"\"\"\n    By-Component Assembly Exports Markdown reader.\n\n    Export reader handles all operations related to reading authored inherited and satisfied statements from exports\n    in Markdown. The reader will read all the markdown files in the exports directory and update the SSP with the\n    inheritance.\n    \"\"\"\n\n    def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan):\n\"\"\"\n        Initialize export reader.\n\n        Arguments:\n            root_path: A root path object where an SSP's inheritance markdown is located.\n            ssp: A system security plan object that will be updated with the inheritance information.\n\n        Notes:\n            The mapped components list is used to track which components have been mapped to controls in the markdown.\n            It can be retrieved with the get_leveraged_components method. This will be empty until the\n            read_exports_from_markdown method is called.\n        \"\"\"\n        self._ssp: ossp.SystemSecurityPlan = ssp\n\n        # Create a dictionary of implemented requirements keyed by control id for merging operations\n        self._implemented_requirements: Dict[str, ossp.ImplementedRequirement] = self._create_impl_req_dict()\n\n        # List of component titles that have been mapped to controls in the Markdown\n        self._mapped_components: List[str] = []\n\n        self._root_path: pathlib.Path = root_path\n\n    def _create_impl_req_dict(self) -> Dict[str, ossp.ImplementedRequirement]:\n\"\"\"Create a dictionary of implemented requirements keyed by control id.\"\"\"\n        impl_req_dict: Dict[str, ossp.ImplementedRequirement] = {}\n        for impl_req in as_list(self._ssp.control_implementation.implemented_requirements):\n            impl_req_dict[impl_req.control_id] = impl_req\n        return impl_req_dict\n\n    def read_exports_from_markdown(self) -> ossp.SystemSecurityPlan:\n\"\"\"Read inheritance markdown and update the SSP with the inheritance information.\"\"\"\n        # Read the information from the markdown files into a dictionary for quick lookup\n        markdown_dict: InheritanceViewDict = self._read_inheritance_markdown_directory()\n\n        # Merge the markdown information into existing the implemented requirements\n        self._merge_exports_implemented_requirements(markdown_dict)\n\n        # Process remaining markdown information that was not in the implemented requirements\n        for control_id, by_comp_dict in markdown_dict.items():\n            if by_comp_dict:\n                logging.debug(f'Adding control mapping {control_id} to implemented requirements')\n                self._add_control_mappings_to_implemented_requirements(control_id, by_comp_dict)\n\n        self._ssp.control_implementation.implemented_requirements = list(self._implemented_requirements.values())\n        return self._ssp\n\n    def get_leveraged_ssp_href(self) -> str:\n\"\"\"Get the href of the leveraged SSP from a markdown file.\"\"\"\n        comp_dirs = os.listdir(self._root_path)\n        if len(comp_dirs) == 0:\n            raise TrestleError('No components were found in the markdown.')\n\n        control_dirs = os.listdir(self._root_path.joinpath(comp_dirs[0]))\n        if len(control_dirs) == 0:\n            raise TrestleError('No controls were found in the markdown for component {comp_dirs[0]}.')\n\n        control_dir = self._root_path.joinpath(comp_dirs[0], control_dirs[0])\n\n        files = [f for f in os.listdir(control_dir) if os.path.isfile(os.path.join(control_dir, f))]\n        if len(files) == 0:\n            raise TrestleError(f'No files were found in the markdown for control {control_dirs[0]}.')\n\n        markdown_file_path = control_dir.joinpath(files[0])\n        reader = InheritanceMarkdownReader(markdown_file_path)\n        return reader.get_leveraged_ssp_reference()\n\n    def get_leveraged_components(self) -> List[str]:\n\"\"\"Get a list of component titles that have been mapped to controls in the Markdown.\"\"\"\n        return self._mapped_components\n\n    def _merge_exports_implemented_requirements(self, markdown_dict: InheritanceViewDict) -> None:\n\"\"\"Merge all exported inheritance info from the markdown into the implemented requirement dict.\"\"\"\n        for implemented_requirement in self._implemented_requirements.values():\n\n            # If the control id existing in the markdown, then update the by_components\n            if implemented_requirement.control_id in markdown_dict:\n\n                # Delete the entry from the markdown_dict once processed to avoid duplicates\n                by_comp_dict: ByComponentDict = markdown_dict.pop(implemented_requirement.control_id)\n\n                self._update_type_with_by_comp(implemented_requirement, by_comp_dict)\n\n            # Update any implemented requirements statements assemblies\n            new_statements: List[ossp.Statement] = []\n\n            for stm in as_list(implemented_requirement.statements):\n                statement_id = getattr(stm, 'statement_id', f'{implemented_requirement.control_id}_smt')\n\n                # If the statement id existing in the markdown, then update the by_components\n                if statement_id in markdown_dict:\n\n                    # Delete the entry from the markdown_dict once processed to avoid duplicates\n                    by_comp_dict: ByComponentDict = markdown_dict.pop(statement_id)\n\n                    self._update_type_with_by_comp(stm, by_comp_dict)\n\n                new_statements.append(stm)\n\n            implemented_requirement.statements = none_if_empty(new_statements)\n\n    def _update_type_with_by_comp(self, with_bycomp: TypeWithByComps, by_comp_dict: ByComponentDict) -> None:\n\"\"\"Update the by_components for a type with by_components.\"\"\"\n        new_by_comp: List[ossp.ByComponent] = []\n\n        by_comp: ossp.ByComponent\n        comp_inheritance_info: Tuple[List[ossp.Inherited], List[ossp.Satisfied]]\n        for by_comp in as_list(with_bycomp.by_components):\n\n            # If the by_component uuid exists in the by_comp_dict, then update it\n            # If not, clear the by_component inheritance information\n            comp_inheritance_info = by_comp_dict.pop(by_comp.component_uuid, ([], []))\n\n            bycomp_interface = ByComponentInterface(by_comp)\n            by_comp = bycomp_interface.reconcile_inheritance_by_component(\n                comp_inheritance_info[0], comp_inheritance_info[1]\n            )\n\n            new_by_comp.append(by_comp)\n\n        # Add any new by_components that were not in the original statement\n        new_by_comp.extend(ExportReader._add_new_by_comps(by_comp_dict))\n        with_bycomp.by_components = none_if_empty(new_by_comp)\n\n    def _add_control_mappings_to_implemented_requirements(\n        self, control_mapping: str, by_comps: ByComponentDict\n    ) -> None:\n\"\"\"Add control mappings to implemented requirements.\"\"\"\n        # Determine if the control id is actually a statement id\n        if '_smt.' in control_mapping:\n            control_id = control_mapping.split('_smt')[0]\n            implemented_req = self._add_or_get_implemented_requirement(control_id)\n            statement = gens.generate_sample_model(ossp.Statement)\n            statement.statement_id = control_mapping\n            statement.by_components = ExportReader._add_new_by_comps(by_comps)\n            implemented_req.statements = as_list(implemented_req.statements)\n            implemented_req.statements.append(statement)\n            implemented_req.statements = sorted(implemented_req.statements, key=lambda x: x.statement_id)\n        else:\n            implemented_req = self._add_or_get_implemented_requirement(control_mapping)\n            implemented_req.by_components = as_list(implemented_req.by_components)\n            implemented_req.by_components.extend(ExportReader._add_new_by_comps(by_comps))\n\n    def _add_or_get_implemented_requirement(self, control_id: str) -> ossp.ImplementedRequirement:\n\"\"\"Add or get implemented requirement from implemented requirements dictionary.\"\"\"\n        if control_id in self._implemented_requirements:\n            return self._implemented_requirements[control_id]\n\n        implemented_requirement = gens.generate_sample_model(ossp.ImplementedRequirement)\n        implemented_requirement.control_id = control_id\n        self._implemented_requirements[control_id] = implemented_requirement\n        return implemented_requirement\n\n    @staticmethod\n    def _add_new_by_comps(by_comp_dict: ByComponentDict) -> List[ossp.ByComponent]:\n\"\"\"Add new by_components to the implemented requirement.\"\"\"\n        new_by_comp: List[ossp.ByComponent] = []\n        for comp_uuid, inheritance_info in by_comp_dict.items():\n            by_comp: ossp.ByComponent = gens.generate_sample_model(ossp.ByComponent)\n            by_comp.component_uuid = comp_uuid\n            by_comp.inherited = none_if_empty(inheritance_info[0])\n            by_comp.satisfied = none_if_empty(inheritance_info[1])\n            new_by_comp.append(by_comp)\n        return new_by_comp\n\n    def _read_inheritance_markdown_directory(self) -> InheritanceViewDict:\n\"\"\"Read all inheritance markdown files and return a dictionary of all the information.\"\"\"\n        markdown_dict: InheritanceViewDict = {}\n\n        # Creating a dictionary to find the component uuid by title for faster lookup\n        uuid_by_title: Dict[str, str] = {}\n        for component in as_list(self._ssp.system_implementation.components):\n            uuid_by_title[component.title] = component.uuid\n\n        for comp_dir in os.listdir(self._root_path):\n            is_comp_leveraged = False\n            for control_dir in os.listdir(os.path.join(self._root_path, comp_dir)):\n                control_dir_path = os.path.join(self._root_path, comp_dir, control_dir)\n\n                # Initialize the by_component dictionary for the control directory\n                # If it exists in the markdown dictionary, then update it with the new information\n                by_comp_dict = markdown_dict.get(control_dir, {})\n\n                for file in os.listdir(control_dir_path):\n                    file_path = pathlib.Path(control_dir_path).joinpath(file)\n                    reader = InheritanceMarkdownReader(file_path)\n                    leveraged_info = reader.process_leveraged_statement_markdown()\n\n                    # If there is no leveraged information, then skip this file\n                    if leveraged_info is None:\n                        continue\n\n                    # If a file has leveraged information, then set the flag to indicate the component is leveraged\n                    is_comp_leveraged = True\n\n                    for comp in leveraged_info.leveraging_comp_titles:\n                        if comp not in uuid_by_title:\n                            keys_as_string = ', '.join(uuid_by_title.keys())\n                            raise TrestleError(\n                                f'Component \"{comp}\" does not exist in the {self._ssp.metadata.title} SSP. '\n                                f'Please use options: {keys_as_string}.'\n                            )\n\n                        comp_uuid = uuid_by_title[comp]\n                        inherited, satisfied = by_comp_dict.get(comp_uuid, ([], []))\n\n                        if leveraged_info.inherited is not None:\n                            inherited.append(leveraged_info.inherited)\n                        if leveraged_info.satisfied is not None:\n                            satisfied.append(leveraged_info.satisfied)\n\n                        by_comp_dict[comp_uuid] = (inherited, satisfied)\n\n                markdown_dict[control_dir] = by_comp_dict\n\n            if is_comp_leveraged:\n                self._mapped_components.append(comp_dir)\n\n        return markdown_dict\n
                                    "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.__init__","title":"__init__(self, root_path, ssp) special","text":"

                                    Initialize export reader.

                                    Parameters:

                                    Name Type Description Default root_path Path

                                    A root path object where an SSP's inheritance markdown is located.

                                    required ssp SystemSecurityPlan

                                    A system security plan object that will be updated with the inheritance information.

                                    required

                                    Notes

                                    The mapped components list is used to track which components have been mapped to controls in the markdown. It can be retrieved with the get_leveraged_components method. This will be empty until the read_exports_from_markdown method is called.

                                    Source code in trestle/core/crm/export_reader.py
                                    def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan):\n\"\"\"\n    Initialize export reader.\n\n    Arguments:\n        root_path: A root path object where an SSP's inheritance markdown is located.\n        ssp: A system security plan object that will be updated with the inheritance information.\n\n    Notes:\n        The mapped components list is used to track which components have been mapped to controls in the markdown.\n        It can be retrieved with the get_leveraged_components method. This will be empty until the\n        read_exports_from_markdown method is called.\n    \"\"\"\n    self._ssp: ossp.SystemSecurityPlan = ssp\n\n    # Create a dictionary of implemented requirements keyed by control id for merging operations\n    self._implemented_requirements: Dict[str, ossp.ImplementedRequirement] = self._create_impl_req_dict()\n\n    # List of component titles that have been mapped to controls in the Markdown\n    self._mapped_components: List[str] = []\n\n    self._root_path: pathlib.Path = root_path\n
                                    "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.get_leveraged_components","title":"get_leveraged_components(self)","text":"

                                    Get a list of component titles that have been mapped to controls in the Markdown.

                                    Source code in trestle/core/crm/export_reader.py
                                    def get_leveraged_components(self) -> List[str]:\n\"\"\"Get a list of component titles that have been mapped to controls in the Markdown.\"\"\"\n    return self._mapped_components\n
                                    "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.get_leveraged_ssp_href","title":"get_leveraged_ssp_href(self)","text":"

                                    Get the href of the leveraged SSP from a markdown file.

                                    Source code in trestle/core/crm/export_reader.py
                                    def get_leveraged_ssp_href(self) -> str:\n\"\"\"Get the href of the leveraged SSP from a markdown file.\"\"\"\n    comp_dirs = os.listdir(self._root_path)\n    if len(comp_dirs) == 0:\n        raise TrestleError('No components were found in the markdown.')\n\n    control_dirs = os.listdir(self._root_path.joinpath(comp_dirs[0]))\n    if len(control_dirs) == 0:\n        raise TrestleError('No controls were found in the markdown for component {comp_dirs[0]}.')\n\n    control_dir = self._root_path.joinpath(comp_dirs[0], control_dirs[0])\n\n    files = [f for f in os.listdir(control_dir) if os.path.isfile(os.path.join(control_dir, f))]\n    if len(files) == 0:\n        raise TrestleError(f'No files were found in the markdown for control {control_dirs[0]}.')\n\n    markdown_file_path = control_dir.joinpath(files[0])\n    reader = InheritanceMarkdownReader(markdown_file_path)\n    return reader.get_leveraged_ssp_reference()\n
                                    "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.read_exports_from_markdown","title":"read_exports_from_markdown(self)","text":"

                                    Read inheritance markdown and update the SSP with the inheritance information.

                                    Source code in trestle/core/crm/export_reader.py
                                    def read_exports_from_markdown(self) -> ossp.SystemSecurityPlan:\n\"\"\"Read inheritance markdown and update the SSP with the inheritance information.\"\"\"\n    # Read the information from the markdown files into a dictionary for quick lookup\n    markdown_dict: InheritanceViewDict = self._read_inheritance_markdown_directory()\n\n    # Merge the markdown information into existing the implemented requirements\n    self._merge_exports_implemented_requirements(markdown_dict)\n\n    # Process remaining markdown information that was not in the implemented requirements\n    for control_id, by_comp_dict in markdown_dict.items():\n        if by_comp_dict:\n            logging.debug(f'Adding control mapping {control_id} to implemented requirements')\n            self._add_control_mappings_to_implemented_requirements(control_id, by_comp_dict)\n\n    self._ssp.control_implementation.implemented_requirements = list(self._implemented_requirements.values())\n    return self._ssp\n
                                    "},{"location":"api_reference/trestle.core.crm.export_writer/","title":"export_writer","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer","title":"trestle.core.crm.export_writer","text":"

                                    Provided interface to write provided and responsibility exports statements to Markdown.

                                    "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter","title":" ExportWriter ","text":"

                                    By-Component Assembly Exports writer.

                                    Export writer handles all operations related to writing provided and responsibility exported statements to Markdown.

                                    Source code in trestle/core/crm/export_writer.py
                                    class ExportWriter:\n\"\"\"\n    By-Component Assembly Exports writer.\n\n    Export writer handles all operations related to writing provided and responsibility exported statements\n    to Markdown.\n    \"\"\"\n\n    def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan, leveraged_ssp_href: str):\n\"\"\"\n        Initialize export writer.\n\n        Arguments:\n            root_path: A root path object where all markdown files and directories should be written.\n            ssp: A system security plan with exports\n        \"\"\"\n        self._ssp: ossp.SystemSecurityPlan = ssp\n        self._root_path: pathlib.Path = root_path\n        self._leveraged_ssp_href: str = leveraged_ssp_href\n\n        # Find all the components and create paths for name\n        self._paths_by_comp: Dict[str, pathlib.Path] = {}\n        for component in as_list(self._ssp.system_implementation.components):\n            self._paths_by_comp[component.uuid] = self._root_path.joinpath(component.title)\n\n    def write_exports_as_markdown(self) -> None:\n\"\"\"Write export statement for leveraged SSP as the inheritance Markdown view.\"\"\"\n        # Process all information under exports in control implementation\n        for implemented_requirement in as_list(self._ssp.control_implementation.implemented_requirements):\n            for by_comp in as_list(implemented_requirement.by_components):\n                self._process_by_component(by_comp, implemented_requirement.control_id)\n\n            for stm in as_list(implemented_requirement.statements):\n                statement_id = getattr(stm, 'statement_id', f'{implemented_requirement.control_id}_smt')\n                for by_comp in as_list(stm.by_components):\n                    self._process_by_component(by_comp, statement_id)\n\n    def _process_by_component(self, by_comp: ossp.ByComponent, control_id: str) -> None:\n\"\"\"Complete the Markdown writing operations for each by-component assembly.\"\"\"\n        if by_comp.component_uuid not in self._paths_by_comp:\n            raise TrestleError(f'Component id {by_comp.component_uuid} is not in the system implementation')\n\n        comp_path: pathlib.Path = self._paths_by_comp[by_comp.component_uuid]\n\n        export_interface: ByComponentInterface = ByComponentInterface(by_comp=by_comp)\n        leveraged_statements: Dict[str, LeveragedStatements] = self._statement_types_from_exports(export_interface)\n\n        # Only create the directory if leveraged statements exist. If not return.\n        if not leveraged_statements:\n            logger.debug(f'Component {by_comp.component_uuid} has no exports for control {control_id}')\n            return\n\n        control_path: pathlib.Path = comp_path.joinpath(control_id)\n        control_path.mkdir(exist_ok=True, parents=True)\n\n        for statement_file_path, leveraged_stm in leveraged_statements.items():\n            statement_path: pathlib.Path = control_path.joinpath(f'{statement_file_path}{const.MARKDOWN_FILE_EXT}')\n            leveraged_stm.write_statement_md(statement_path)\n\n    def _statement_types_from_exports(self, export_interface: ByComponentInterface) -> Dict[str, LeveragedStatements]:\n\"\"\"Process all exports and return a file basename and LeveragedStatement object for each.\"\"\"\n        all_statements: Dict[str, LeveragedStatements] = {}\n\n        for responsibility in export_interface.get_isolated_responsibilities():\n            all_statements[responsibility.uuid] = StatementResponsibility(\n                responsibility.uuid, responsibility.description, self._leveraged_ssp_href\n            )\n\n        for provided in export_interface.get_isolated_provided():\n            all_statements[provided.uuid\n                           ] = StatementProvided(provided.uuid, provided.description, self._leveraged_ssp_href)\n\n        for responsibility, provided in export_interface.get_export_sets():\n            path = f'{provided.uuid}_{responsibility.uuid}'\n            all_statements[path] = StatementTree(\n                provided.uuid,\n                provided.description,\n                responsibility.uuid,\n                responsibility.description,\n                self._leveraged_ssp_href\n            )\n\n        return all_statements\n
                                    "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter.__init__","title":"__init__(self, root_path, ssp, leveraged_ssp_href) special","text":"

                                    Initialize export writer.

                                    Parameters:

                                    Name Type Description Default root_path Path

                                    A root path object where all markdown files and directories should be written.

                                    required ssp SystemSecurityPlan

                                    A system security plan with exports

                                    required Source code in trestle/core/crm/export_writer.py
                                    def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan, leveraged_ssp_href: str):\n\"\"\"\n    Initialize export writer.\n\n    Arguments:\n        root_path: A root path object where all markdown files and directories should be written.\n        ssp: A system security plan with exports\n    \"\"\"\n    self._ssp: ossp.SystemSecurityPlan = ssp\n    self._root_path: pathlib.Path = root_path\n    self._leveraged_ssp_href: str = leveraged_ssp_href\n\n    # Find all the components and create paths for name\n    self._paths_by_comp: Dict[str, pathlib.Path] = {}\n    for component in as_list(self._ssp.system_implementation.components):\n        self._paths_by_comp[component.uuid] = self._root_path.joinpath(component.title)\n
                                    "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter.write_exports_as_markdown","title":"write_exports_as_markdown(self)","text":"

                                    Write export statement for leveraged SSP as the inheritance Markdown view.

                                    Source code in trestle/core/crm/export_writer.py
                                    def write_exports_as_markdown(self) -> None:\n\"\"\"Write export statement for leveraged SSP as the inheritance Markdown view.\"\"\"\n    # Process all information under exports in control implementation\n    for implemented_requirement in as_list(self._ssp.control_implementation.implemented_requirements):\n        for by_comp in as_list(implemented_requirement.by_components):\n            self._process_by_component(by_comp, implemented_requirement.control_id)\n\n        for stm in as_list(implemented_requirement.statements):\n            statement_id = getattr(stm, 'statement_id', f'{implemented_requirement.control_id}_smt')\n            for by_comp in as_list(stm.by_components):\n                self._process_by_component(by_comp, statement_id)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/","title":"leveraged_statements","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements","title":"trestle.core.crm.leveraged_statements","text":"

                                    Handle writing of inherited statements to markdown.

                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.component_mapping_default","title":"component_mapping_default: List[Dict[str, str]]","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo","title":" InheritanceInfo dataclass","text":"

                                    Class to capture component inheritance information.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    @dataclass\nclass InheritanceInfo:\n\"\"\"Class to capture component inheritance information.\"\"\"\n\n    leveraging_comp_titles: List[str]\n    inherited: Optional[ssp.Inherited]\n    satisfied: Optional[ssp.Satisfied]\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.inherited","title":"inherited: Optional[trestle.oscal.ssp.Inherited] dataclass-field","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.leveraging_comp_titles","title":"leveraging_comp_titles: List[str] dataclass-field","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.satisfied","title":"satisfied: Optional[trestle.oscal.ssp.Satisfied] dataclass-field","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.__init__","title":"__init__(self, leveraging_comp_titles, inherited, satisfied) special","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader","title":" InheritanceMarkdownReader ","text":"

                                    Class to read leveraged statement information from Markdown.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    class InheritanceMarkdownReader:\n\"\"\"Class to read leveraged statement information from Markdown.\"\"\"\n\n    def __init__(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n        # Save the file name for logging\n        self._leveraged_statement_file = leveraged_statement_file\n\n        md_api: MarkdownAPI = MarkdownAPI()\n\n        yaml_header, inheritance_md = md_api.processor.process_markdown(leveraged_statement_file)\n        self._yaml_header: Dict[str, Any] = yaml_header\n        self._inheritance_md: DocsMarkdownNode = inheritance_md\n\n    def process_leveraged_statement_markdown(self) -> Optional[InheritanceInfo]:\n\"\"\"\n        Read inheritance information from Markdown.\n\n        Returns:\n            Optional InheritanceInfo - A list of mapped component titles, an optional satisfied statement and an\n            optional inherited statement\n\n        Notes:\n            Returns inheritance information in the context of the leveraging SSP. If no leveraging component titles are\n            mapped in the yaml header None will be returned. The satisfied and inherited fields are\n            generated and returned to added information to by-component assemblies for\n            the mapped leveraging components.\n\n        \"\"\"\n        leveraging_comps: List[str] = []\n        inherited_statement: Optional[ssp.Inherited] = None\n        satisfied_statement: Optional[ssp.Satisfied] = None\n\n        leveraging_comp_header_value: List[Dict[str, str]] = self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n\n        # If there are no mapped components, return early\n        if not leveraging_comp_header_value or leveraging_comp_header_value == component_mapping_default:\n            return None\n        else:\n            for comp_dicts in leveraging_comp_header_value:\n                for comp_title in comp_dicts.values():\n                    leveraging_comps.append(comp_title)\n\n        statement_info: Dict[str, str] = self._yaml_header[const.TRESTLE_STATEMENT_TAG]\n\n        if const.PROVIDED_UUID in statement_info:\n            # Set inherited\n\n            provided_description = self.get_provided_description()\n            if provided_description is None:\n                raise TrestleError(f'Provided statement cannot be empty in {self._leveraged_statement_file}')\n\n            inherited_statement = gens.generate_sample_model(ssp.Inherited)\n\n            inherited_statement.description = provided_description\n            inherited_statement.provided_uuid = statement_info[const.PROVIDED_UUID]\n\n        if const.RESPONSIBILITY_UUID in statement_info:\n            # Set satisfied\n            satisfied_description = self.get_satisfied_description()\n            if satisfied_description is None:\n                raise TrestleError(f'Satisfied statement cannot be empty in {self._leveraged_statement_file}')\n\n            satisfied_statement = gens.generate_sample_model(ssp.Satisfied)\n\n            satisfied_statement.description = satisfied_description\n            satisfied_statement.responsibility_uuid = statement_info[const.RESPONSIBILITY_UUID]\n\n        return InheritanceInfo(leveraging_comps, inherited_statement, satisfied_statement)\n\n    def get_leveraged_ssp_reference(self) -> str:\n\"\"\"Return the leveraged SSP reference in the yaml header.\"\"\"\n        return self._yaml_header[const.TRESTLE_GLOBAL_TAG][const.LEVERAGED_SSP][const.HREF]\n\n    def get_satisfied_description(self) -> Optional[str]:\n\"\"\"Return the satisfied description in the Markdown.\"\"\"\n        node = self._inheritance_md.get_node_for_key(const.SATISFIED_STATEMENT_DESCRIPTION, False)\n        if node is not None:\n            return self.strip_heading_and_comments(node.content.raw_text)\n        else:\n            return None\n\n    def get_provided_description(self) -> Optional[str]:\n\"\"\"Return the provided description in the Markdown.\"\"\"\n        node = self._inheritance_md.get_node_for_key(const.PROVIDED_STATEMENT_DESCRIPTION, False)\n        if node is not None:\n            return self.strip_heading_and_comments(node.content.raw_text)\n        else:\n            return None\n\n    def get_leveraged_component_header_value(self) -> Dict[str, str]:\n\"\"\"Provide the leveraged component value in the yaml header.\"\"\"\n        return self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n\n    @staticmethod\n    def strip_heading_and_comments(markdown_text: str) -> str:\n\"\"\"Remove the heading and comments from lines to get the multi-line paragraph.\"\"\"\n        lines = markdown_text.split('\\n')\n        non_heading_comment_lines = []\n        inside_heading = False\n        inside_comment = False\n\n        for line in lines:\n            if line.startswith('#'):\n                inside_heading = True\n            elif line.startswith('<!--'):\n                inside_comment = True\n                if line.rstrip().endswith('-->'):\n                    inside_comment = False\n                continue\n            elif line.strip() == '':\n                inside_heading = False\n                inside_comment = False\n\n            if not inside_heading and not inside_comment:\n                non_heading_comment_lines.append(line)\n\n        stripped_markdown = '\\n'.join(non_heading_comment_lines).strip()\n        return stripped_markdown\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.__init__","title":"__init__(self, leveraged_statement_file) special","text":"

                                    Initialize the class.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def __init__(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n    # Save the file name for logging\n    self._leveraged_statement_file = leveraged_statement_file\n\n    md_api: MarkdownAPI = MarkdownAPI()\n\n    yaml_header, inheritance_md = md_api.processor.process_markdown(leveraged_statement_file)\n    self._yaml_header: Dict[str, Any] = yaml_header\n    self._inheritance_md: DocsMarkdownNode = inheritance_md\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_leveraged_component_header_value","title":"get_leveraged_component_header_value(self)","text":"

                                    Provide the leveraged component value in the yaml header.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def get_leveraged_component_header_value(self) -> Dict[str, str]:\n\"\"\"Provide the leveraged component value in the yaml header.\"\"\"\n    return self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_leveraged_ssp_reference","title":"get_leveraged_ssp_reference(self)","text":"

                                    Return the leveraged SSP reference in the yaml header.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def get_leveraged_ssp_reference(self) -> str:\n\"\"\"Return the leveraged SSP reference in the yaml header.\"\"\"\n    return self._yaml_header[const.TRESTLE_GLOBAL_TAG][const.LEVERAGED_SSP][const.HREF]\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_provided_description","title":"get_provided_description(self)","text":"

                                    Return the provided description in the Markdown.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def get_provided_description(self) -> Optional[str]:\n\"\"\"Return the provided description in the Markdown.\"\"\"\n    node = self._inheritance_md.get_node_for_key(const.PROVIDED_STATEMENT_DESCRIPTION, False)\n    if node is not None:\n        return self.strip_heading_and_comments(node.content.raw_text)\n    else:\n        return None\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_satisfied_description","title":"get_satisfied_description(self)","text":"

                                    Return the satisfied description in the Markdown.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def get_satisfied_description(self) -> Optional[str]:\n\"\"\"Return the satisfied description in the Markdown.\"\"\"\n    node = self._inheritance_md.get_node_for_key(const.SATISFIED_STATEMENT_DESCRIPTION, False)\n    if node is not None:\n        return self.strip_heading_and_comments(node.content.raw_text)\n    else:\n        return None\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.process_leveraged_statement_markdown","title":"process_leveraged_statement_markdown(self)","text":"

                                    Read inheritance information from Markdown.

                                    Returns:

                                    Type Description Optional[trestle.core.crm.leveraged_statements.InheritanceInfo]

                                    Optional InheritanceInfo - A list of mapped component titles, an optional satisfied statement and an optional inherited statement

                                    Notes

                                    Returns inheritance information in the context of the leveraging SSP. If no leveraging component titles are mapped in the yaml header None will be returned. The satisfied and inherited fields are generated and returned to added information to by-component assemblies for the mapped leveraging components.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def process_leveraged_statement_markdown(self) -> Optional[InheritanceInfo]:\n\"\"\"\n    Read inheritance information from Markdown.\n\n    Returns:\n        Optional InheritanceInfo - A list of mapped component titles, an optional satisfied statement and an\n        optional inherited statement\n\n    Notes:\n        Returns inheritance information in the context of the leveraging SSP. If no leveraging component titles are\n        mapped in the yaml header None will be returned. The satisfied and inherited fields are\n        generated and returned to added information to by-component assemblies for\n        the mapped leveraging components.\n\n    \"\"\"\n    leveraging_comps: List[str] = []\n    inherited_statement: Optional[ssp.Inherited] = None\n    satisfied_statement: Optional[ssp.Satisfied] = None\n\n    leveraging_comp_header_value: List[Dict[str, str]] = self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n\n    # If there are no mapped components, return early\n    if not leveraging_comp_header_value or leveraging_comp_header_value == component_mapping_default:\n        return None\n    else:\n        for comp_dicts in leveraging_comp_header_value:\n            for comp_title in comp_dicts.values():\n                leveraging_comps.append(comp_title)\n\n    statement_info: Dict[str, str] = self._yaml_header[const.TRESTLE_STATEMENT_TAG]\n\n    if const.PROVIDED_UUID in statement_info:\n        # Set inherited\n\n        provided_description = self.get_provided_description()\n        if provided_description is None:\n            raise TrestleError(f'Provided statement cannot be empty in {self._leveraged_statement_file}')\n\n        inherited_statement = gens.generate_sample_model(ssp.Inherited)\n\n        inherited_statement.description = provided_description\n        inherited_statement.provided_uuid = statement_info[const.PROVIDED_UUID]\n\n    if const.RESPONSIBILITY_UUID in statement_info:\n        # Set satisfied\n        satisfied_description = self.get_satisfied_description()\n        if satisfied_description is None:\n            raise TrestleError(f'Satisfied statement cannot be empty in {self._leveraged_statement_file}')\n\n        satisfied_statement = gens.generate_sample_model(ssp.Satisfied)\n\n        satisfied_statement.description = satisfied_description\n        satisfied_statement.responsibility_uuid = statement_info[const.RESPONSIBILITY_UUID]\n\n    return InheritanceInfo(leveraging_comps, inherited_statement, satisfied_statement)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.strip_heading_and_comments","title":"strip_heading_and_comments(markdown_text) staticmethod","text":"

                                    Remove the heading and comments from lines to get the multi-line paragraph.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    @staticmethod\ndef strip_heading_and_comments(markdown_text: str) -> str:\n\"\"\"Remove the heading and comments from lines to get the multi-line paragraph.\"\"\"\n    lines = markdown_text.split('\\n')\n    non_heading_comment_lines = []\n    inside_heading = False\n    inside_comment = False\n\n    for line in lines:\n        if line.startswith('#'):\n            inside_heading = True\n        elif line.startswith('<!--'):\n            inside_comment = True\n            if line.rstrip().endswith('-->'):\n                inside_comment = False\n            continue\n        elif line.strip() == '':\n            inside_heading = False\n            inside_comment = False\n\n        if not inside_heading and not inside_comment:\n            non_heading_comment_lines.append(line)\n\n    stripped_markdown = '\\n'.join(non_heading_comment_lines).strip()\n    return stripped_markdown\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements","title":" LeveragedStatements (ABC) ","text":"

                                    Abstract class for managing leveraged statements.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    class LeveragedStatements(ABC):\n\"\"\"Abstract class for managing leveraged statements.\"\"\"\n\n    def __init__(self, leveraged_ssp_reference: str) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self._md_file: Optional[MDWriter] = None\n        self.header_comment_dict: Dict[str, str] = {\n            const.TRESTLE_LEVERAGING_COMP_TAG: const.YAML_LEVERAGING_COMP_COMMENT,\n            const.TRESTLE_STATEMENT_TAG: const.YAML_LEVERAGED_COMMENT\n        }\n        self.merged_header_dict: Dict[str, Any] = {\n            const.TRESTLE_STATEMENT_TAG: '',\n            const.TRESTLE_LEVERAGING_COMP_TAG: component_mapping_default,\n            const.TRESTLE_GLOBAL_TAG: {\n                const.LEVERAGED_SSP: {\n                    const.HREF: leveraged_ssp_reference\n                }\n            }\n        }\n\n    @abstractmethod\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write inheritance information to a single markdown file.\"\"\"\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements.__init__","title":"__init__(self, leveraged_ssp_reference) special","text":"

                                    Initialize the class.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def __init__(self, leveraged_ssp_reference: str) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self._md_file: Optional[MDWriter] = None\n    self.header_comment_dict: Dict[str, str] = {\n        const.TRESTLE_LEVERAGING_COMP_TAG: const.YAML_LEVERAGING_COMP_COMMENT,\n        const.TRESTLE_STATEMENT_TAG: const.YAML_LEVERAGED_COMMENT\n    }\n    self.merged_header_dict: Dict[str, Any] = {\n        const.TRESTLE_STATEMENT_TAG: '',\n        const.TRESTLE_LEVERAGING_COMP_TAG: component_mapping_default,\n        const.TRESTLE_GLOBAL_TAG: {\n            const.LEVERAGED_SSP: {\n                const.HREF: leveraged_ssp_reference\n            }\n        }\n    }\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                    Write inheritance information to a single markdown file.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    @abstractmethod\ndef write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write inheritance information to a single markdown file.\"\"\"\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided","title":" StatementProvided (LeveragedStatements) ","text":"

                                    Concrete class for managing provided statements.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    class StatementProvided(LeveragedStatements):\n\"\"\"Concrete class for managing provided statements.\"\"\"\n\n    def __init__(\n        self,\n        provided_uuid: str,\n        provided_description: str,\n        leveraged_ssp_reference: str,\n    ) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self.provided_uuid = provided_uuid\n        self.provided_description = provided_description\n        super().__init__(leveraged_ssp_reference)\n\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write provided statements to a markdown file.\"\"\"\n        self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n        if self._md_file.exists():\n            return self.update_statement_md(leveraged_statement_file)\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided statements in a markdown file.\"\"\"\n        md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n        self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def _add_generated_content(self) -> None:\n        self.merged_header_dict[const.TRESTLE_STATEMENT_TAG] = {const.PROVIDED_UUID: self.provided_uuid}\n        self._md_file.add_yaml_header(self.merged_header_dict)\n\n        self._md_file.new_header(level=1, title=const.PROVIDED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.provided_description)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided.__init__","title":"__init__(self, provided_uuid, provided_description, leveraged_ssp_reference) special","text":"Source code in trestle/core/crm/leveraged_statements.py
                                    def __init__(\n    self,\n    provided_uuid: str,\n    provided_description: str,\n    leveraged_ssp_reference: str,\n) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self.provided_uuid = provided_uuid\n    self.provided_description = provided_description\n    super().__init__(leveraged_ssp_reference)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided.update_statement_md","title":"update_statement_md(self, leveraged_statement_file)","text":"

                                    Update provided statements in a markdown file.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided statements in a markdown file.\"\"\"\n    md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n    self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                    Write provided statements to a markdown file.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write provided statements to a markdown file.\"\"\"\n    self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n    if self._md_file.exists():\n        return self.update_statement_md(leveraged_statement_file)\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility","title":" StatementResponsibility (LeveragedStatements) ","text":"

                                    Concrete class for managing responsibility statements.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    class StatementResponsibility(LeveragedStatements):\n\"\"\"Concrete class for managing responsibility statements.\"\"\"\n\n    def __init__(\n        self,\n        responsibility_uuid: str,\n        responsibility_description: str,\n        leveraged_ssp_reference: str,\n    ) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self.responsibility_uuid = responsibility_uuid\n        self.responsibility_description = responsibility_description\n        self.satisfied_description = ''\n        super().__init__(leveraged_ssp_reference)\n\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write responsibility statements to a markdown file.\"\"\"\n        self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n        if self._md_file.exists():\n            return self.update_statement_md(leveraged_statement_file)\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update responsibility statements in a markdown file.\"\"\"\n        md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n        self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n        satisfied_description = md_reader.get_satisfied_description()\n        if satisfied_description is not None:\n            self.satisfied_description = satisfied_description\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def _add_generated_content(self) -> None:\n        self.merged_header_dict[const.TRESTLE_STATEMENT_TAG] = {const.RESPONSIBILITY_UUID: self.responsibility_uuid}\n        self._md_file.add_yaml_header(self.merged_header_dict)\n\n        self._md_file.new_header(level=1, title=const.RESPONSIBILITY_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.responsibility_description)\n        self._md_file.new_header(level=1, title=const.SATISFIED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(const.SATISFIED_STATEMENT_COMMENT)\n        self._md_file.new_line(self.satisfied_description)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility.__init__","title":"__init__(self, responsibility_uuid, responsibility_description, leveraged_ssp_reference) special","text":"Source code in trestle/core/crm/leveraged_statements.py
                                    def __init__(\n    self,\n    responsibility_uuid: str,\n    responsibility_description: str,\n    leveraged_ssp_reference: str,\n) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self.responsibility_uuid = responsibility_uuid\n    self.responsibility_description = responsibility_description\n    self.satisfied_description = ''\n    super().__init__(leveraged_ssp_reference)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility.update_statement_md","title":"update_statement_md(self, leveraged_statement_file)","text":"

                                    Update responsibility statements in a markdown file.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update responsibility statements in a markdown file.\"\"\"\n    md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n    self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n    satisfied_description = md_reader.get_satisfied_description()\n    if satisfied_description is not None:\n        self.satisfied_description = satisfied_description\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                    Write responsibility statements to a markdown file.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write responsibility statements to a markdown file.\"\"\"\n    self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n    if self._md_file.exists():\n        return self.update_statement_md(leveraged_statement_file)\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree","title":" StatementTree (LeveragedStatements) ","text":"

                                    Concrete class for managing provided and responsibility statements.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    class StatementTree(LeveragedStatements):\n\"\"\"Concrete class for managing provided and responsibility statements.\"\"\"\n\n    def __init__(\n        self,\n        provided_uuid: str,\n        provided_description: str,\n        responsibility_uuid: str,\n        responsibility_description: str,\n        leveraged_ssp_reference: str\n    ) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self.provided_uuid = provided_uuid\n        self.provided_description = provided_description\n        self.responsibility_uuid = responsibility_uuid\n        self.responsibility_description = responsibility_description\n        self.satisfied_description = ''\n        super().__init__(leveraged_ssp_reference)\n\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write a provided and responsibility statements to a markdown file.\"\"\"\n        self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n        if self._md_file.exists():\n            return self.update_statement_md(leveraged_statement_file)\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided and responsibility statements in a markdown file.\"\"\"\n        md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n        self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n        satisfied_description = md_reader.get_satisfied_description()\n        if satisfied_description is not None:\n            self.satisfied_description = satisfied_description\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def _add_generated_content(self) -> None:\n        statement_dict: Dict[str, str] = {\n            const.PROVIDED_UUID: self.provided_uuid, const.RESPONSIBILITY_UUID: self.responsibility_uuid\n        }\n\n        self.merged_header_dict[const.TRESTLE_STATEMENT_TAG] = statement_dict\n        self._md_file.add_yaml_header(self.merged_header_dict)\n\n        self._md_file.new_header(level=1, title=const.PROVIDED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.provided_description)\n        self._md_file.new_header(level=1, title=const.RESPONSIBILITY_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.responsibility_description)\n        self._md_file.new_header(level=1, title=const.SATISFIED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(const.SATISFIED_STATEMENT_COMMENT)\n        self._md_file.new_line(self.satisfied_description)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree.__init__","title":"__init__(self, provided_uuid, provided_description, responsibility_uuid, responsibility_description, leveraged_ssp_reference) special","text":"Source code in trestle/core/crm/leveraged_statements.py
                                    def __init__(\n    self,\n    provided_uuid: str,\n    provided_description: str,\n    responsibility_uuid: str,\n    responsibility_description: str,\n    leveraged_ssp_reference: str\n) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self.provided_uuid = provided_uuid\n    self.provided_description = provided_description\n    self.responsibility_uuid = responsibility_uuid\n    self.responsibility_description = responsibility_description\n    self.satisfied_description = ''\n    super().__init__(leveraged_ssp_reference)\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree.update_statement_md","title":"update_statement_md(self, leveraged_statement_file)","text":"

                                    Update provided and responsibility statements in a markdown file.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided and responsibility statements in a markdown file.\"\"\"\n    md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n    self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n    satisfied_description = md_reader.get_satisfied_description()\n    if satisfied_description is not None:\n        self.satisfied_description = satisfied_description\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                    Write a provided and responsibility statements to a markdown file.

                                    Source code in trestle/core/crm/leveraged_statements.py
                                    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write a provided and responsibility statements to a markdown file.\"\"\"\n    self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n    if self._md_file.exists():\n        return self.update_statement_md(leveraged_statement_file)\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                    "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/","title":"ssp_inheritance_api","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api","title":"trestle.core.crm.ssp_inheritance_api","text":"

                                    API for updating inheritance information in SSPs.

                                    "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI","title":" SSPInheritanceAPI ","text":"

                                    API for updating inheritance information in SSPs through inheritance markdown.

                                    Source code in trestle/core/crm/ssp_inheritance_api.py
                                    class SSPInheritanceAPI():\n\"\"\"API for updating inheritance information in SSPs through inheritance markdown.\"\"\"\n\n    def __init__(self, inheritance_md_path: pathlib.Path, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the SSP Inheritance API class.\"\"\"\n        self._inheritance_markdown_path: pathlib.Path = inheritance_md_path\n        self._trestle_root: pathlib.Path = trestle_root\n\n    def write_inheritance_as_markdown(\n        self, leveraged_ssp_reference: str, catalog_api: Optional[CatalogAPI] = None\n    ) -> None:\n\"\"\"\n        Write inheritance information to markdown.\n\n        Args:\n            leveraged_ssp_reference: Location of the SSP to write inheritance information from.\n            catalog_api: Catalog API to filter inheritance information by catalog.\n\n        Notes:\n            If a catalog API is provided, the written controls in the markdown will be filtered by the catalog.\n        \"\"\"\n        leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n        if catalog_api is not None:\n            control_imp: ossp.ControlImplementation = leveraged_ssp.control_implementation\n\n            new_imp_requirements: List[ossp.ImplementedRequirement] = []\n            for imp_requirement in as_list(control_imp.implemented_requirements):\n                control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n                if control is not None:\n                    new_imp_requirements.append(imp_requirement)\n            control_imp.implemented_requirements = new_imp_requirements\n\n            leveraged_ssp.control_implementation = control_imp\n\n        export_writer: ExportWriter = ExportWriter(\n            self._inheritance_markdown_path, leveraged_ssp, leveraged_ssp_reference\n        )\n        export_writer.write_exports_as_markdown()\n\n    def update_ssp_inheritance(self, ssp: ossp.SystemSecurityPlan) -> None:\n\"\"\"\n        Update inheritance information in SSP.\n\n        Args:\n            ssp: SSP to update with inheritance information.\n        \"\"\"\n        logger.debug('Reading inheritance information from markdown.')\n        reader = ExportReader(self._inheritance_markdown_path, ssp)\n        ssp = reader.read_exports_from_markdown()\n\n        leveraged_ssp_reference = reader.get_leveraged_ssp_href()\n\n        leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n        link: common.Link = common.Link(href=leveraged_ssp_reference)\n        leveraged_auths: List[ossp.LeveragedAuthorization] = []\n        leveraged_auth: ossp.LeveragedAuthorization = gens.generate_sample_model(ossp.LeveragedAuthorization)\n        leveraged_components: List[str] = reader.get_leveraged_components()\n\n        if not leveraged_components:\n            logger.warning(\n                'No leveraged components mapped to the SSP. '\n                'Please edit the inheritance markdown to include the leveraged authorization.'\n            )\n        else:\n            existing_leveraged_auth: ossp.LeveragedAuthorization = self._leveraged_auth_from_existing(\n                as_list(ssp.system_implementation.leveraged_authorizations), link\n            )\n            if existing_leveraged_auth is not None:\n                leveraged_auth = existing_leveraged_auth\n            else:\n                leveraged_auth.links = as_list(leveraged_auth.links)\n                leveraged_auth.links.append(link)\n\n            leveraged_auth.title = f'Leveraged Authorization for {leveraged_ssp.metadata.title}'\n            leveraged_auths.append(leveraged_auth)\n\n        # Overwrite the leveraged authorization in the SSP. The only leveraged authorization should be the one\n        # coming from inheritance view\n        ssp.system_implementation.leveraged_authorizations = none_if_empty(leveraged_auths)\n\n        self._reconcile_components(ssp, leveraged_ssp, leveraged_components, leveraged_auth)\n\n    def _fetch_leveraged_ssp(self, leveraged_ssp_reference: str) -> ossp.SystemSecurityPlan:\n\"\"\"Fetch the leveraged SSP.\"\"\"\n        leveraged_ssp: ossp.SystemSecurityPlan\n        fetcher = FetcherFactory.get_fetcher(self._trestle_root, leveraged_ssp_reference)\n        try:\n            leveraged_ssp, _ = fetcher.get_oscal()\n        except TrestleError as e:\n            raise TrestleError(f'Unable to fetch ssp from {leveraged_ssp_reference}: {e}')\n        return leveraged_ssp\n\n    def _reconcile_components(\n        self,\n        ssp: ossp.SystemSecurityPlan,\n        leveraged_ssp: ossp.SystemSecurityPlan,\n        leveraged_components: List[str],\n        leveraged_auth: ossp.LeveragedAuthorization\n    ) -> None:\n\"\"\"Reconcile components in the leveraging SSP with those in the leveraged SSP.\"\"\"\n        mapped_components: Dict[str, ossp.SystemComponent] = {}\n        for component in as_list(leveraged_ssp.system_implementation.components):\n            if component.title in leveraged_components:\n                mapped_components[component.uuid] = component\n\n        new_components: List[ossp.SystemComponent] = []\n        for component in as_list(ssp.system_implementation.components):\n            props_dict: Dict[str, str] = {prop.name: prop.value for prop in as_list(component.props)}\n\n            # If this component is part of the original SSP components, add\n            # and continue\n            if const.LEV_AUTH_UUID not in props_dict:\n                new_components.append(component)\n                continue\n\n            # If the leveraged component already exists, update the title, description, type, and status\n            original_comp_uuid = props_dict[const.INHERITED_UUID]\n            if original_comp_uuid in mapped_components:\n                original_component = mapped_components.pop(original_comp_uuid)\n                self._update_leveraged_system_component(component, original_component, leveraged_auth.uuid)\n                new_components.append(component)\n\n        # Add any remaining components to the new components\n        for component in mapped_components.values():\n            new_component: ossp.SystemComponent = gens.generate_sample_model(ossp.SystemComponent)\n            self._update_leveraged_system_component(new_component, component, leveraged_auth.uuid)\n            logger.debug(f'Adding component {new_component.title} to components.')\n            new_components.append(new_component)\n\n        ssp.system_implementation.components = new_components\n\n    @staticmethod\n    def _update_leveraged_system_component(\n        new_comp: ossp.SystemComponent, original_comp: ossp.SystemComponent, leveraged_auth_id: str\n    ) -> None:\n\"\"\"Create a leveraged system component in the context of a leveraging system component.\"\"\"\n        new_comp.type = original_comp.type\n        new_comp.title = original_comp.title\n        new_comp.description = original_comp.description\n        new_comp.status = original_comp.status\n\n        new_comp.props = [\n            common.Property(name=const.IMPLEMENTATION_POINT, value=const.IMPLEMENTATION_POINT_EXTERNAL),\n            common.Property(name=const.LEV_AUTH_UUID, value=leveraged_auth_id),\n            common.Property(name=const.INHERITED_UUID, value=original_comp.uuid)\n        ]\n\n    def _leveraged_auth_from_existing(\n        self, leveraged_authorizations: List[ossp.LeveragedAuthorization], criteria_link: common.Link\n    ) -> Optional[ossp.LeveragedAuthorization]:\n\"\"\"Return the leveraged authorization if it is present in the ssp.\"\"\"\n        for leveraged_auth in leveraged_authorizations:\n            if leveraged_auth.links and any(link.href == criteria_link.href for link in leveraged_auth.links):\n                return leveraged_auth\n        return None\n
                                    "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI.__init__","title":"__init__(self, inheritance_md_path, trestle_root) special","text":"

                                    Initialize the SSP Inheritance API class.

                                    Source code in trestle/core/crm/ssp_inheritance_api.py
                                    def __init__(self, inheritance_md_path: pathlib.Path, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the SSP Inheritance API class.\"\"\"\n    self._inheritance_markdown_path: pathlib.Path = inheritance_md_path\n    self._trestle_root: pathlib.Path = trestle_root\n
                                    "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI.update_ssp_inheritance","title":"update_ssp_inheritance(self, ssp)","text":"

                                    Update inheritance information in SSP.

                                    Parameters:

                                    Name Type Description Default ssp SystemSecurityPlan

                                    SSP to update with inheritance information.

                                    required Source code in trestle/core/crm/ssp_inheritance_api.py
                                    def update_ssp_inheritance(self, ssp: ossp.SystemSecurityPlan) -> None:\n\"\"\"\n    Update inheritance information in SSP.\n\n    Args:\n        ssp: SSP to update with inheritance information.\n    \"\"\"\n    logger.debug('Reading inheritance information from markdown.')\n    reader = ExportReader(self._inheritance_markdown_path, ssp)\n    ssp = reader.read_exports_from_markdown()\n\n    leveraged_ssp_reference = reader.get_leveraged_ssp_href()\n\n    leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n    link: common.Link = common.Link(href=leveraged_ssp_reference)\n    leveraged_auths: List[ossp.LeveragedAuthorization] = []\n    leveraged_auth: ossp.LeveragedAuthorization = gens.generate_sample_model(ossp.LeveragedAuthorization)\n    leveraged_components: List[str] = reader.get_leveraged_components()\n\n    if not leveraged_components:\n        logger.warning(\n            'No leveraged components mapped to the SSP. '\n            'Please edit the inheritance markdown to include the leveraged authorization.'\n        )\n    else:\n        existing_leveraged_auth: ossp.LeveragedAuthorization = self._leveraged_auth_from_existing(\n            as_list(ssp.system_implementation.leveraged_authorizations), link\n        )\n        if existing_leveraged_auth is not None:\n            leveraged_auth = existing_leveraged_auth\n        else:\n            leveraged_auth.links = as_list(leveraged_auth.links)\n            leveraged_auth.links.append(link)\n\n        leveraged_auth.title = f'Leveraged Authorization for {leveraged_ssp.metadata.title}'\n        leveraged_auths.append(leveraged_auth)\n\n    # Overwrite the leveraged authorization in the SSP. The only leveraged authorization should be the one\n    # coming from inheritance view\n    ssp.system_implementation.leveraged_authorizations = none_if_empty(leveraged_auths)\n\n    self._reconcile_components(ssp, leveraged_ssp, leveraged_components, leveraged_auth)\n
                                    "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI.write_inheritance_as_markdown","title":"write_inheritance_as_markdown(self, leveraged_ssp_reference, catalog_api=None)","text":"

                                    Write inheritance information to markdown.

                                    Parameters:

                                    Name Type Description Default leveraged_ssp_reference str

                                    Location of the SSP to write inheritance information from.

                                    required catalog_api Optional[trestle.core.catalog.catalog_api.CatalogAPI]

                                    Catalog API to filter inheritance information by catalog.

                                    None

                                    Notes

                                    If a catalog API is provided, the written controls in the markdown will be filtered by the catalog.

                                    Source code in trestle/core/crm/ssp_inheritance_api.py
                                    def write_inheritance_as_markdown(\n    self, leveraged_ssp_reference: str, catalog_api: Optional[CatalogAPI] = None\n) -> None:\n\"\"\"\n    Write inheritance information to markdown.\n\n    Args:\n        leveraged_ssp_reference: Location of the SSP to write inheritance information from.\n        catalog_api: Catalog API to filter inheritance information by catalog.\n\n    Notes:\n        If a catalog API is provided, the written controls in the markdown will be filtered by the catalog.\n    \"\"\"\n    leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n    if catalog_api is not None:\n        control_imp: ossp.ControlImplementation = leveraged_ssp.control_implementation\n\n        new_imp_requirements: List[ossp.ImplementedRequirement] = []\n        for imp_requirement in as_list(control_imp.implemented_requirements):\n            control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n            if control is not None:\n                new_imp_requirements.append(imp_requirement)\n        control_imp.implemented_requirements = new_imp_requirements\n\n        leveraged_ssp.control_implementation = control_imp\n\n    export_writer: ExportWriter = ExportWriter(\n        self._inheritance_markdown_path, leveraged_ssp, leveraged_ssp_reference\n    )\n    export_writer.write_exports_as_markdown()\n
                                    "},{"location":"api_reference/trestle.core.docs_control_writer/","title":"docs_control_writer","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer","title":"trestle.core.docs_control_writer","text":"

                                    Handle writing of controls to markdown for docs purposes.

                                    "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter","title":" DocsControlWriter (ControlWriter) ","text":"

                                    Class to write controls as markdown for docs purposes.

                                    Source code in trestle/core/docs_control_writer.py
                                    class DocsControlWriter(ControlWriter):\n\"\"\"Class to write controls as markdown for docs purposes.\"\"\"\n\n    def write_control_with_sections(\n        self,\n        control: cat.Control,\n        profile: prof.Profile,\n        group_title: str,\n        sections: List[str],\n        sections_dict: Optional[Dict[str, str]] = None,\n        label_column: bool = True,\n        add_group_to_title: bool = False\n    ) -> str:\n\"\"\"Write the control into markdown file with specified sections.\"\"\"\n        self._md_file = MDWriter(None)\n        self._sections_dict = sections_dict if sections_dict else {}\n        tag_pattern = '{: #[.]}'  # noqa: FS003 - not f string but tag\n        if not isinstance(group_title, str):\n            raise TrestleError(f'Group title must be provided and be a string, instead received: {group_title}')\n\n        for section in sections:\n            if 'statement' == section:\n                self._add_control_statement(control, group_title, add_group_to_title, tag_pattern=tag_pattern)\n\n            elif const.OBJECTIVE_PART == section:\n                self._add_control_objective(control, tag_pattern=tag_pattern)\n\n            elif 'table_of_parameters' == section:\n                self.get_param_table(\n                    control, label_column, section_dict=sections_dict, tag_pattern=tag_pattern, md_file=self._md_file\n                )\n            else:\n                self._add_one_section(control, profile, section, tag_pattern=tag_pattern)\n\n        return '\\n'.join(self._md_file._lines)\n\n    def get_control_statement_ssp(self, control: cat.Control) -> List[str]:\n\"\"\"Get the control statement as formatted markdown from a control formatted for SSP.\"\"\"\n        self._md_file = MDWriter(None)\n        self._add_control_statement_ssp(control)\n        return self._md_file.get_lines()\n\n    def get_param_table(\n        self,\n        control: cat.Control,\n        label_column: bool = False,\n        section_dict: Optional[Dict[str, str]] = None,\n        tag_pattern: str = None,\n        md_file: MDWriter = None\n    ) -> List[str]:\n\"\"\"Get parameters of a control as a markdown table for ssp_io, with optional third label column.\"\"\"\n\n        def _get_displayname_if_exists(param_id: str) -> str:\n            for param in as_filtered_list(control.params, lambda p: p.id == param_id):\n                for prop in as_filtered_list(param.props, lambda p: p.name == const.DISPLAY_NAME):\n                    return prop.value\n            return param_id\n\n        param_dict = ControlInterface.get_control_param_dict(control, False)\n\n        if param_dict:\n            if md_file:\n                self._md_file = md_file\n            else:\n                self._md_file = MDWriter(None)\n            header_title = 'Table of Parameters'\n            if section_dict:\n                header_title = section_dict.get(const.TABLE_OF_PARAMS_PART, 'Table of Parameters')\n            self._md_file.new_paragraph()\n            self._md_file.new_header(level=2, title=header_title, add_new_line_after_header=not tag_pattern)\n            if tag_pattern:\n                self._md_file.new_line(tag_pattern.replace('[.]', header_title.replace(' ', '-').lower()))\n                self._md_file.new_paragraph()\n            self._md_file.set_indent_level(-1)\n            if label_column:\n                self._md_file.new_table(\n                    [\n                        [\n                            _get_displayname_if_exists(key),\n                            ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_EMPTY_STRING),\n                            ControlInterface.param_to_str(param_dict[key], ParameterRep.LABEL_OR_CHOICES, True),\n                        ] for key in param_dict.keys()\n                    ], ['Parameter ID', 'Values', 'Label or Choices']\n                )\n            else:\n                self._md_file.new_table(\n                    [\n                        [\n                            _get_displayname_if_exists(key),\n                            ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_LABEL_OR_CHOICES)\n                        ] for key in param_dict.keys()\n                    ], ['Parameter ID', 'Values']\n                )\n            self._md_file.set_indent_level(-1)\n            if tag_pattern:\n                bottom_tag_pattern = '{: #\\\"Parameters for [.]\\\" caption-side=\\\"top\\\"}'  # noqa: FS003 - not f string\n                control_id = self._get_pretty_control_id_if_exists(control)\n                self._md_file.new_line(bottom_tag_pattern.replace('[.]', control_id))\n                self._md_file.new_paragraph()\n            return self._md_file.get_lines()\n\n        return []\n\n    def _add_control_statement(\n        self, control: cat.Control, group_title: str, print_group_title: bool = True, tag_pattern: str = None\n    ) -> None:\n\"\"\"Add the control statement and items to the md file.\"\"\"\n        self._md_file.new_paragraph()\n\n        group_name = ''\n        control_title = control.title\n\n        if print_group_title:\n            group_name = ' \\[' + group_title + '\\]'\n\n        control_id = self._get_pretty_control_id_if_exists(control)\n\n        title = f'{control_id} -{group_name} {control_title}'\n\n        header_title = self._sections_dict.get(const.STATEMENT, 'Control Statement')\n        self._md_file.new_header(level=1, title=title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', control.id))\n            self._md_file.new_paragraph()\n\n        self._md_file.new_header(level=2, title=header_title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', header_title.replace(' ', '-').lower()))\n            self._md_file.new_paragraph()\n\n        self._md_file.set_indent_level(-1)\n        self._add_part_and_its_items(control, const.STATEMENT, const.ITEM)\n        self._md_file.set_indent_level(-1)\n\n    def _add_control_objective(self, control: cat.Control, tag_pattern: str = None) -> None:\n        if control.parts:\n            for part in control.parts:\n                if part.name == const.OBJECTIVE_PART:\n                    self._md_file.new_paragraph()\n                    heading_title = self._sections_dict.get(const.OBJECTIVE_PART, 'Control Objective')\n                    self._md_file.new_header(level=2, title=heading_title, add_new_line_after_header=not tag_pattern)\n                    if tag_pattern:\n                        self._md_file.new_line(tag_pattern.replace('[.]', heading_title.replace(' ', '-').lower()))\n                        self._md_file.new_paragraph()\n                    self._md_file.set_indent_level(-1)\n                    self._add_part_and_its_items(control, const.OBJECTIVE_PART, const.OBJECTIVE_PART)\n                    self._md_file.set_indent_level(-1)\n                    return\n\n    def _add_one_section(\n        self, control: cat.Control, profile: prof.Profile, section: str, tag_pattern: Optional[str] = None\n    ) -> None:\n\"\"\"Add specific control section.\"\"\"\n        prose = ControlInterface.get_control_section_prose(control, section)\n        if prose:\n            section_title = self._sections_dict.get(section, section)\n            heading_title = f'{section_title}'\n            self._md_file.new_header(level=2, title=heading_title, add_new_line_after_header=not tag_pattern)\n            if tag_pattern:\n                self._md_file.new_line(tag_pattern.replace('[.]', heading_title.replace(' ', '-').lower()))\n                self._md_file.new_paragraph()\n            self._md_file.new_line(prose)\n            self._md_file.new_paragraph()\n        else:\n            # write parts and subparts if exist\n            part_infos = ControlInterface.get_all_add_info(control.id, profile)\n            for part_info in part_infos:\n                if part_info.name == section:\n                    self._write_part_info(part_info, section, tag_pattern)\n                    break\n\n    def _write_part_info(\n        self,\n        part_info: PartInfo,\n        section_name: str,\n        tag_pattern: Optional[str] = None,\n        section_prefix: str = '',\n        heading_level: int = 2\n    ) -> None:\n        section_title = self._sections_dict.get(section_name, part_info.name)\n\n        heading_title = f'{section_title}'\n        tag_section_name = section_prefix + f'{section_title}'\n        tag_section_name = re.sub(const.MATCH_ALL_EXCEPT_LETTERS_UNDERSCORE_SPACE_REGEX, '', tag_section_name)\n        tag_section_name = tag_section_name.replace(' ', '-').replace('_', '-').lower()\n        self._md_file.new_header(level=heading_level, title=heading_title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', tag_section_name))\n            self._md_file.new_paragraph()\n        prose = '' if part_info.prose is None else part_info.prose\n        self._md_file.new_line(prose)\n        self._md_file.new_paragraph()\n\n        for subpart_info in as_list(part_info.parts):\n            self._write_part_info(\n                subpart_info, subpart_info.name, tag_pattern, tag_section_name + '-', heading_level + 1\n            )\n\n    def _get_pretty_control_id_if_exists(self, control: cat.Control) -> str:\n        control_id = control.id.upper()\n        if control.props:\n            # Take control id from the properties\n            for prop in control.props:\n                if prop.name == 'label':\n                    control_id = prop.value\n                    break\n        return control_id\n\n    def _add_control_statement_ssp(self, control: cat.Control) -> None:\n\"\"\"Add the control statement and items to the markdown SSP.\"\"\"\n        self._md_file.new_paragraph()\n        label = ControlInterface.get_label(control)\n        label = label if label else control.id.upper()\n        title = f'{label} - {control.title}'\n        self._md_file.new_header(level=1, title=title)\n        self._md_file.new_header(level=2, title='Control Statement')\n        self._md_file.set_indent_level(-1)\n        self._add_part_and_its_items(control, const.STATEMENT, const.ITEM)\n        self._md_file.set_indent_level(-1)\n
                                    "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter.get_control_statement_ssp","title":"get_control_statement_ssp(self, control)","text":"

                                    Get the control statement as formatted markdown from a control formatted for SSP.

                                    Source code in trestle/core/docs_control_writer.py
                                    def get_control_statement_ssp(self, control: cat.Control) -> List[str]:\n\"\"\"Get the control statement as formatted markdown from a control formatted for SSP.\"\"\"\n    self._md_file = MDWriter(None)\n    self._add_control_statement_ssp(control)\n    return self._md_file.get_lines()\n
                                    "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter.get_param_table","title":"get_param_table(self, control, label_column=False, section_dict=None, tag_pattern=None, md_file=None)","text":"

                                    Get parameters of a control as a markdown table for ssp_io, with optional third label column.

                                    Source code in trestle/core/docs_control_writer.py
                                    def get_param_table(\n    self,\n    control: cat.Control,\n    label_column: bool = False,\n    section_dict: Optional[Dict[str, str]] = None,\n    tag_pattern: str = None,\n    md_file: MDWriter = None\n) -> List[str]:\n\"\"\"Get parameters of a control as a markdown table for ssp_io, with optional third label column.\"\"\"\n\n    def _get_displayname_if_exists(param_id: str) -> str:\n        for param in as_filtered_list(control.params, lambda p: p.id == param_id):\n            for prop in as_filtered_list(param.props, lambda p: p.name == const.DISPLAY_NAME):\n                return prop.value\n        return param_id\n\n    param_dict = ControlInterface.get_control_param_dict(control, False)\n\n    if param_dict:\n        if md_file:\n            self._md_file = md_file\n        else:\n            self._md_file = MDWriter(None)\n        header_title = 'Table of Parameters'\n        if section_dict:\n            header_title = section_dict.get(const.TABLE_OF_PARAMS_PART, 'Table of Parameters')\n        self._md_file.new_paragraph()\n        self._md_file.new_header(level=2, title=header_title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', header_title.replace(' ', '-').lower()))\n            self._md_file.new_paragraph()\n        self._md_file.set_indent_level(-1)\n        if label_column:\n            self._md_file.new_table(\n                [\n                    [\n                        _get_displayname_if_exists(key),\n                        ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_EMPTY_STRING),\n                        ControlInterface.param_to_str(param_dict[key], ParameterRep.LABEL_OR_CHOICES, True),\n                    ] for key in param_dict.keys()\n                ], ['Parameter ID', 'Values', 'Label or Choices']\n            )\n        else:\n            self._md_file.new_table(\n                [\n                    [\n                        _get_displayname_if_exists(key),\n                        ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_LABEL_OR_CHOICES)\n                    ] for key in param_dict.keys()\n                ], ['Parameter ID', 'Values']\n            )\n        self._md_file.set_indent_level(-1)\n        if tag_pattern:\n            bottom_tag_pattern = '{: #\\\"Parameters for [.]\\\" caption-side=\\\"top\\\"}'  # noqa: FS003 - not f string\n            control_id = self._get_pretty_control_id_if_exists(control)\n            self._md_file.new_line(bottom_tag_pattern.replace('[.]', control_id))\n            self._md_file.new_paragraph()\n        return self._md_file.get_lines()\n\n    return []\n
                                    "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter.write_control_with_sections","title":"write_control_with_sections(self, control, profile, group_title, sections, sections_dict=None, label_column=True, add_group_to_title=False)","text":"

                                    Write the control into markdown file with specified sections.

                                    Source code in trestle/core/docs_control_writer.py
                                    def write_control_with_sections(\n    self,\n    control: cat.Control,\n    profile: prof.Profile,\n    group_title: str,\n    sections: List[str],\n    sections_dict: Optional[Dict[str, str]] = None,\n    label_column: bool = True,\n    add_group_to_title: bool = False\n) -> str:\n\"\"\"Write the control into markdown file with specified sections.\"\"\"\n    self._md_file = MDWriter(None)\n    self._sections_dict = sections_dict if sections_dict else {}\n    tag_pattern = '{: #[.]}'  # noqa: FS003 - not f string but tag\n    if not isinstance(group_title, str):\n        raise TrestleError(f'Group title must be provided and be a string, instead received: {group_title}')\n\n    for section in sections:\n        if 'statement' == section:\n            self._add_control_statement(control, group_title, add_group_to_title, tag_pattern=tag_pattern)\n\n        elif const.OBJECTIVE_PART == section:\n            self._add_control_objective(control, tag_pattern=tag_pattern)\n\n        elif 'table_of_parameters' == section:\n            self.get_param_table(\n                control, label_column, section_dict=sections_dict, tag_pattern=tag_pattern, md_file=self._md_file\n            )\n        else:\n            self._add_one_section(control, profile, section, tag_pattern=tag_pattern)\n\n    return '\\n'.join(self._md_file._lines)\n
                                    "},{"location":"api_reference/trestle.core.draw_io/","title":"draw_io","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io","title":"trestle.core.draw_io","text":"

                                    Functionality for reading information from a drawio file.

                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO","title":" DrawIO ","text":"

                                    Access and process drawio data / metadata.

                                    Source code in trestle/core/draw_io.py
                                    class DrawIO():\n\"\"\"Access and process drawio data / metadata.\"\"\"\n\n    def __init__(self, file_path: pathlib.Path) -> None:\n\"\"\"\n        Load drawio object into memory.\n\n        args:\n            file_path: Path to the drawio object.\n        \"\"\"\n        self.file_path: pathlib.Path = file_path\n        self._load()\n        self.banned_keys = ['id', 'label']\n\n    def _load(self) -> None:\n\"\"\"Load the file.\"\"\"\n        if not self.file_path.exists() or self.file_path.is_dir():\n            raise TrestleError(f'Candidate drawio file {str(self.file_path)} does not exist or is a directory')\n        try:\n            self.raw_xml = defusedxml.ElementTree.parse(self.file_path, forbid_dtd=True)\n        except Exception as e:\n            raise TrestleError(f'Exception loading Element tree from file: {e}')\n        self.mx_file = self.raw_xml.getroot()\n        if not self.mx_file.tag == 'mxfile':\n            raise TrestleError('DrawIO file is not a draw io file (mxfile)')\n        self.diagrams = []\n        for diagram in list(self.mx_file):\n            # Determine if compressed or not\n            # Assumption 1 mxGraphModel\n            n_children = len(list(diagram))\n            if n_children == 0:\n                # Compressed object\n                self.diagrams.append(self._uncompress(diagram.text))\n            elif n_children == 1:\n                self.diagrams.append(list(diagram)[0])\n            else:\n                raise TrestleError('Unhandled behaviour in drawio read.')\n\n    def _uncompress(self, compressed_text: str) -> Element:\n\"\"\"\n        Given a compressed object from a drawio file return an xml element for the mxGraphModel.\n\n        Args:\n            compressed_text: A compressed mxGraphModel from inside an mxfile\n\n        Returns:\n            An element containing the mxGraphModel\n        \"\"\"\n        # Assume b64 encode\n        decoded = base64.b64decode(compressed_text)\n        clean_text = unquote(zlib.decompress(decoded, -15).decode(const.FILE_ENCODING))\n        element = defusedxml.ElementTree.fromstring(clean_text, forbid_dtd=True)\n        if not element.tag == 'mxGraphModel':\n            raise TrestleError('Unknown data structure within a compressed drawio file.')\n        return element\n\n    def get_metadata(self) -> List[Dict[str, str]]:\n\"\"\"Get metadata from each tab if it exists or provide an empty dict.\"\"\"\n        # Note that id and label are special for drawio.\n        md_list: List[Dict[str, str]] = []\n        for diagram in self.diagrams:\n            md_dict: Dict[str, str] = {}\n            # Drawio creates data within a root and then an object element type\n            children = list(diagram)\n            root_obj = children[0]\n            md_objects = root_obj.findall('object')\n            # Should always be true - to test presumptions.\n            if len(md_objects) == 0:\n                md_list.append(md_dict)\n                continue\n            items = md_objects[0].items()\n            for item in items:\n                key = item[0]\n                val = item[1]\n                if key in self.banned_keys:\n                    continue\n                md_dict[key] = val\n            md_list.append(md_dict)\n        return md_list\n\n    @classmethod\n    def restructure_metadata(cls, input_dict: Dict[str, str]) -> Dict[str, Any]:\n\"\"\"Restructure metadata into a hierarchial dict assuming a period separator.\"\"\"\n        # get the list of duplicate keys\n        # Get a count of keys\n        result = {}\n        key_map = {}\n        for keys in input_dict.keys():\n            stub = keys.split('.')[0]\n            tmp = key_map.get(stub, [])\n            tmp.append(keys)\n            key_map[stub] = tmp\n\n        for key, values in key_map.items():\n            holding = {}\n            if len(values) == 1 and key == values[0]:\n                result[key] = input_dict[key]\n            else:\n                for value in values:\n                    holding[value.split('.', 1)[-1]] = input_dict[value]\n                result[key] = cls.restructure_metadata(holding)\n        return result\n\n    def write_drawio_with_metadata(\n        self, path: pathlib.Path, metadata: Dict, diagram_metadata_idx: int, target_path: pathlib.Path = None\n    ) -> None:\n\"\"\"\n        Write modified metadata to drawio file.\n\n        Writes given metadata to 'object' element attributes inside of the selected drawio diagram element.\n        Currently supports writing only uncompressed elements.\n\n        Args:\n            path: path to write modified drawio file to\n            metadata: dictionary of modified metadata to insert to drawio\n            diagram_metadata_idx: index of diagram which metadata was modified\n            target_path: if not provided the changes will be written to path\n        \"\"\"\n        flattened_dict = self._flatten_dictionary(metadata)\n        if diagram_metadata_idx >= len(list(self.diagrams)):\n            raise TrestleError(f'Drawio file {path} does not contain a diagram for index {diagram_metadata_idx}')\n\n        diagram = list(self.diagrams)[diagram_metadata_idx]\n        children = list(diagram)\n        root_obj = children[0]\n        md_objects = root_obj.findall('object')\n        if len(md_objects) == 0:\n            raise TrestleError(f'Unable to write metadata, diagram in drawio file {path} does not have objects.')\n\n        for key in md_objects[0].attrib.copy():\n            if key not in flattened_dict.keys() and key not in self.banned_keys:\n                # outdated key delete\n                del md_objects[0].attrib[key]\n                continue\n            if key in self.banned_keys:\n                continue\n            md_objects[0].attrib[key] = flattened_dict[key]\n        for key in flattened_dict.keys():\n            if key in self.banned_keys:\n                continue\n            md_objects[0].attrib[key] = flattened_dict[key]\n        parent_diagram = self.mx_file.findall('diagram')[diagram_metadata_idx]\n        if len(parent_diagram.findall('mxGraphModel')) == 0:\n            parent_diagram.insert(0, diagram)\n\n        if target_path:\n            self.raw_xml.write(target_path)\n        else:\n            self.raw_xml.write(path)\n\n    def _flatten_dictionary(self, metadata: Dict, parent_key='', separator='.') -> Dict[str, str]:\n\"\"\"Flatten hierarchial dict back to xml attributes.\"\"\"\n        items = []\n        for key, value in metadata.items():\n            new_key = parent_key + separator + key if parent_key else key\n            if isinstance(value, Dict):\n                items.extend(self._flatten_dictionary(value, new_key, separator).items())\n            else:\n                items.append((new_key, value))\n        return dict(items)\n
                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.__init__","title":"__init__(self, file_path) special","text":"

                                    Load drawio object into memory.

                                    Parameters:

                                    Name Type Description Default file_path Path

                                    Path to the drawio object.

                                    required Source code in trestle/core/draw_io.py
                                    def __init__(self, file_path: pathlib.Path) -> None:\n\"\"\"\n    Load drawio object into memory.\n\n    args:\n        file_path: Path to the drawio object.\n    \"\"\"\n    self.file_path: pathlib.Path = file_path\n    self._load()\n    self.banned_keys = ['id', 'label']\n
                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.get_metadata","title":"get_metadata(self)","text":"

                                    Get metadata from each tab if it exists or provide an empty dict.

                                    Source code in trestle/core/draw_io.py
                                    def get_metadata(self) -> List[Dict[str, str]]:\n\"\"\"Get metadata from each tab if it exists or provide an empty dict.\"\"\"\n    # Note that id and label are special for drawio.\n    md_list: List[Dict[str, str]] = []\n    for diagram in self.diagrams:\n        md_dict: Dict[str, str] = {}\n        # Drawio creates data within a root and then an object element type\n        children = list(diagram)\n        root_obj = children[0]\n        md_objects = root_obj.findall('object')\n        # Should always be true - to test presumptions.\n        if len(md_objects) == 0:\n            md_list.append(md_dict)\n            continue\n        items = md_objects[0].items()\n        for item in items:\n            key = item[0]\n            val = item[1]\n            if key in self.banned_keys:\n                continue\n            md_dict[key] = val\n        md_list.append(md_dict)\n    return md_list\n
                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.restructure_metadata","title":"restructure_metadata(input_dict) classmethod","text":"

                                    Restructure metadata into a hierarchial dict assuming a period separator.

                                    Source code in trestle/core/draw_io.py
                                    @classmethod\ndef restructure_metadata(cls, input_dict: Dict[str, str]) -> Dict[str, Any]:\n\"\"\"Restructure metadata into a hierarchial dict assuming a period separator.\"\"\"\n    # get the list of duplicate keys\n    # Get a count of keys\n    result = {}\n    key_map = {}\n    for keys in input_dict.keys():\n        stub = keys.split('.')[0]\n        tmp = key_map.get(stub, [])\n        tmp.append(keys)\n        key_map[stub] = tmp\n\n    for key, values in key_map.items():\n        holding = {}\n        if len(values) == 1 and key == values[0]:\n            result[key] = input_dict[key]\n        else:\n            for value in values:\n                holding[value.split('.', 1)[-1]] = input_dict[value]\n            result[key] = cls.restructure_metadata(holding)\n    return result\n
                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.write_drawio_with_metadata","title":"write_drawio_with_metadata(self, path, metadata, diagram_metadata_idx, target_path=None)","text":"

                                    Write modified metadata to drawio file.

                                    Writes given metadata to 'object' element attributes inside of the selected drawio diagram element. Currently supports writing only uncompressed elements.

                                    Parameters:

                                    Name Type Description Default path Path

                                    path to write modified drawio file to

                                    required metadata Dict

                                    dictionary of modified metadata to insert to drawio

                                    required diagram_metadata_idx int

                                    index of diagram which metadata was modified

                                    required target_path Path

                                    if not provided the changes will be written to path

                                    None Source code in trestle/core/draw_io.py
                                    def write_drawio_with_metadata(\n    self, path: pathlib.Path, metadata: Dict, diagram_metadata_idx: int, target_path: pathlib.Path = None\n) -> None:\n\"\"\"\n    Write modified metadata to drawio file.\n\n    Writes given metadata to 'object' element attributes inside of the selected drawio diagram element.\n    Currently supports writing only uncompressed elements.\n\n    Args:\n        path: path to write modified drawio file to\n        metadata: dictionary of modified metadata to insert to drawio\n        diagram_metadata_idx: index of diagram which metadata was modified\n        target_path: if not provided the changes will be written to path\n    \"\"\"\n    flattened_dict = self._flatten_dictionary(metadata)\n    if diagram_metadata_idx >= len(list(self.diagrams)):\n        raise TrestleError(f'Drawio file {path} does not contain a diagram for index {diagram_metadata_idx}')\n\n    diagram = list(self.diagrams)[diagram_metadata_idx]\n    children = list(diagram)\n    root_obj = children[0]\n    md_objects = root_obj.findall('object')\n    if len(md_objects) == 0:\n        raise TrestleError(f'Unable to write metadata, diagram in drawio file {path} does not have objects.')\n\n    for key in md_objects[0].attrib.copy():\n        if key not in flattened_dict.keys() and key not in self.banned_keys:\n            # outdated key delete\n            del md_objects[0].attrib[key]\n            continue\n        if key in self.banned_keys:\n            continue\n        md_objects[0].attrib[key] = flattened_dict[key]\n    for key in flattened_dict.keys():\n        if key in self.banned_keys:\n            continue\n        md_objects[0].attrib[key] = flattened_dict[key]\n    parent_diagram = self.mx_file.findall('diagram')[diagram_metadata_idx]\n    if len(parent_diagram.findall('mxGraphModel')) == 0:\n        parent_diagram.insert(0, diagram)\n\n    if target_path:\n        self.raw_xml.write(target_path)\n    else:\n        self.raw_xml.write(path)\n
                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator","title":" DrawIOMetadataValidator ","text":"

                                    Validator to check whether drawio metadata meets validation expectations.

                                    Source code in trestle/core/draw_io.py
                                    class DrawIOMetadataValidator():\n\"\"\"Validator to check whether drawio metadata meets validation expectations.\"\"\"\n\n    def __init__(self, template_path: pathlib.Path, must_be_first_tab: bool = True) -> None:\n\"\"\"\n        Initialize drawio validator.\n\n        Args:\n            template_path: Path to a templated drawio file where metadata will be looked up on the first tab only.\n            must_be_first_tab: Whether to search the candidate file for a metadata across multiple tabs.\n        \"\"\"\n        self.template_path = template_path\n        self.must_be_first_tab = must_be_first_tab\n        # Load metadat from template\n        template_drawio = DrawIO(self.template_path)\n        # Zero index as must be first tab\n        self.template_metadata = template_drawio.get_metadata()[0]\n        self.template_version = MarkdownValidator.extract_template_version(self.template_metadata)\n        if self.template_version not in str(self.template_path):\n            raise TrestleError(\n                f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n                + f'Move the template to the folder {self.template_version}'\n            )\n        if 'Version' in self.template_metadata.keys() and self.template_metadata['Version'] != self.template_version:\n            raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n\n    def validate(self, candidate: pathlib.Path) -> bool:\n\"\"\"\n        Run drawio validation against a candidate file.\n\n        Args:\n            candidate: The path to a candidate markdown file to be validated.\n\n        Returns:\n            Whether or not the validation passes.\n\n        Raises:\n            err.TrestleError: If a file IO / formatting error occurs.\n        \"\"\"\n        logging.info(f'Validating drawio file {candidate} against template file {self.template_path}')\n        candidate_drawio = DrawIO(candidate)\n        drawio_metadata = candidate_drawio.get_metadata()\n\n        if self.must_be_first_tab:\n            return MarkdownValidator.compare_keys(self.template_metadata, drawio_metadata[0])\n        for md_tab in drawio_metadata:\n            status = MarkdownValidator.compare_keys(self.template_metadata, md_tab)\n            if status:\n                return status\n        return False\n
                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator.__init__","title":"__init__(self, template_path, must_be_first_tab=True) special","text":"

                                    Initialize drawio validator.

                                    Parameters:

                                    Name Type Description Default template_path Path

                                    Path to a templated drawio file where metadata will be looked up on the first tab only.

                                    required must_be_first_tab bool

                                    Whether to search the candidate file for a metadata across multiple tabs.

                                    True Source code in trestle/core/draw_io.py
                                    def __init__(self, template_path: pathlib.Path, must_be_first_tab: bool = True) -> None:\n\"\"\"\n    Initialize drawio validator.\n\n    Args:\n        template_path: Path to a templated drawio file where metadata will be looked up on the first tab only.\n        must_be_first_tab: Whether to search the candidate file for a metadata across multiple tabs.\n    \"\"\"\n    self.template_path = template_path\n    self.must_be_first_tab = must_be_first_tab\n    # Load metadat from template\n    template_drawio = DrawIO(self.template_path)\n    # Zero index as must be first tab\n    self.template_metadata = template_drawio.get_metadata()[0]\n    self.template_version = MarkdownValidator.extract_template_version(self.template_metadata)\n    if self.template_version not in str(self.template_path):\n        raise TrestleError(\n            f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n            + f'Move the template to the folder {self.template_version}'\n        )\n    if 'Version' in self.template_metadata.keys() and self.template_metadata['Version'] != self.template_version:\n        raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n
                                    "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator.validate","title":"validate(self, candidate)","text":"

                                    Run drawio validation against a candidate file.

                                    Parameters:

                                    Name Type Description Default candidate Path

                                    The path to a candidate markdown file to be validated.

                                    required

                                    Returns:

                                    Type Description bool

                                    Whether or not the validation passes.

                                    Exceptions:

                                    Type Description err.TrestleError

                                    If a file IO / formatting error occurs.

                                    Source code in trestle/core/draw_io.py
                                    def validate(self, candidate: pathlib.Path) -> bool:\n\"\"\"\n    Run drawio validation against a candidate file.\n\n    Args:\n        candidate: The path to a candidate markdown file to be validated.\n\n    Returns:\n        Whether or not the validation passes.\n\n    Raises:\n        err.TrestleError: If a file IO / formatting error occurs.\n    \"\"\"\n    logging.info(f'Validating drawio file {candidate} against template file {self.template_path}')\n    candidate_drawio = DrawIO(candidate)\n    drawio_metadata = candidate_drawio.get_metadata()\n\n    if self.must_be_first_tab:\n        return MarkdownValidator.compare_keys(self.template_metadata, drawio_metadata[0])\n    for md_tab in drawio_metadata:\n        status = MarkdownValidator.compare_keys(self.template_metadata, md_tab)\n        if status:\n            return status\n    return False\n
                                    "},{"location":"api_reference/trestle.core.duplicates_validator/","title":"duplicates_validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator","title":"trestle.core.duplicates_validator","text":"

                                    Validate by confirming no duplicate uuids.

                                    "},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator.DuplicatesValidator","title":" DuplicatesValidator (Validator) ","text":"

                                    Validator to check for duplicate uuids and param_ids in the model.

                                    Source code in trestle/core/duplicates_validator.py
                                    class DuplicatesValidator(Validator):\n\"\"\"Validator to check for duplicate uuids and param_ids in the model.\"\"\"\n\n    def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n        Test if the model is valid and contains no duplicate uuids or param_ids.\n\n        args:\n            model: An Oscal model that can be passed to the validator.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if the model does not contain duplicate uuid's.\n        \"\"\"\n        if not ModelUtils.has_no_duplicate_values_by_name(model, 'uuid'):\n            return False\n        # only profile, comp-def and ssp have set-params and only set-params have param_id\n        # param_id is required to be unique in profiles but not in other models\n        if isinstance(model, Profile):\n            return ModelUtils.has_no_duplicate_values_by_name(model, 'param_id')\n        return True\n
                                    "},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator.DuplicatesValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator.DuplicatesValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                    Test if the model is valid and contains no duplicate uuids or param_ids.

                                    Parameters:

                                    Name Type Description Default model OscalBaseModel

                                    An Oscal model that can be passed to the validator.

                                    required quiet bool

                                    Don't report msgs unless invalid.

                                    required

                                    Returns:

                                    Type Description bool

                                    True (valid) if the model does not contain duplicate uuid's.

                                    Source code in trestle/core/duplicates_validator.py
                                    def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n    Test if the model is valid and contains no duplicate uuids or param_ids.\n\n    args:\n        model: An Oscal model that can be passed to the validator.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if the model does not contain duplicate uuid's.\n    \"\"\"\n    if not ModelUtils.has_no_duplicate_values_by_name(model, 'uuid'):\n        return False\n    # only profile, comp-def and ssp have set-params and only set-params have param_id\n    # param_id is required to be unique in profiles but not in other models\n    if isinstance(model, Profile):\n        return ModelUtils.has_no_duplicate_values_by_name(model, 'param_id')\n    return True\n
                                    "},{"location":"api_reference/trestle.core.generators/","title":"generators","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators","title":"trestle.core.generators","text":"

                                    Capabilities to allow the generation of various oscal objects.

                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.TG","title":"TG","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_base64","title":"sample_base64","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_base64_value","title":"sample_base64_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_date_value","title":"sample_date_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_method","title":"sample_method","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_observation_type_valid_value","title":"sample_observation_type_valid_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_task_valid_value","title":"sample_task_valid_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.type_base64","title":"type_base64","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.generate_sample_model","title":"generate_sample_model(model, include_optional=False, depth=-1)","text":"

                                    Given a model class, generate an object of that class with sample values.

                                    Can generate optional variables with an enabled flag. Any array objects will have a single entry injected into it.

                                    Note: Trestle generate will not activate recursive loops irrespective of the depth flag.

                                    Parameters:

                                    Name Type Description Default model Union[Type[~TG], List[~TG], Dict[str, ~TG]]

                                    The model type provided. Typically for a user as an OscalBaseModel Subclass.

                                    required include_optional bool

                                    Whether or not to generate optional fields.

                                    False depth int

                                    Depth of the tree at which optional fields are generated. Negative values (default) removes the limit.

                                    -1

                                    Returns:

                                    Type Description ~TG

                                    The generated instance with a pro-forma values filled out as best as possible.

                                    Source code in trestle/core/generators.py
                                    def generate_sample_model(\n    model: Union[Type[TG], List[TG], Dict[str, TG]], include_optional: bool = False, depth: int = -1\n) -> TG:\n\"\"\"Given a model class, generate an object of that class with sample values.\n\n    Can generate optional variables with an enabled flag. Any array objects will have a single entry injected into it.\n\n    Note: Trestle generate will not activate recursive loops irrespective of the depth flag.\n\n    Args:\n        model: The model type provided. Typically for a user as an OscalBaseModel Subclass.\n        include_optional: Whether or not to generate optional fields.\n        depth: Depth of the tree at which optional fields are generated. Negative values (default) removes the limit.\n\n    Returns:\n        The generated instance with a pro-forma values filled out as best as possible.\n    \"\"\"\n    effective_optional = include_optional and not depth == 0\n\n    model_type = model\n    # This block normalizes model type down to\n    if utils.is_collection_field_type(model):  # type: ignore\n        model_type = utils.get_origin(model)  # type: ignore\n        model = utils.get_inner_type(model)  # type: ignore\n    model = cast(TG, model)  # type: ignore\n\n    model_dict = {}  # type: ignore\n    # this block is needed to avoid situations where an inbuilt is inside a list / dict.\n    # the only time dict ever appears is with include_all, which is handled specially\n    # the only type of collection possible after OSCAL 1.0.0 is list\n    if safe_is_sub(model, OscalBaseModel):\n        for field in model.__fields__:  # type: ignore\n            if model_type in [OscalVersion]:\n                model_dict[field] = OSCAL_VERSION\n                break\n            if field == 'include_all':\n                if include_optional:\n                    model_dict[field] = {}\n                continue\n            outer_type = model.__fields__[field].outer_type_  # type: ignore\n            # next appears to be needed for python 3.7\n            if utils.get_origin(outer_type) == Union:\n                outer_type = outer_type.__args__[0]\n            if model.__fields__[field].required or effective_optional:  # type: ignore\n                # FIXME could be ForwardRef('SystemComponentStatus')\n                if utils.is_collection_field_type(outer_type):\n                    inner_type = utils.get_inner_type(outer_type)\n                    if inner_type == model:\n                        continue\n                    model_dict[field] = generate_sample_model(\n                        outer_type, include_optional=include_optional, depth=depth - 1\n                    )\n                elif is_by_type(outer_type):\n                    model_dict[field] = generate_sample_value_by_type(outer_type, field)\n                elif safe_is_sub(outer_type, OscalBaseModel):\n                    model_dict[field] = generate_sample_model(\n                        outer_type, include_optional=include_optional, depth=depth - 1\n                    )\n                else:\n                    # Handle special cases (hacking)\n                    if model_type in [Base64Datatype]:\n                        model_dict[field] = sample_base64_value\n                    elif model_type in [Base64]:\n                        if field == 'filename':\n                            model_dict[field] = sample_base64.filename\n                        elif field == 'media_type':\n                            model_dict[field] = sample_base64.media_type\n                        elif field == 'value':\n                            model_dict[field] = sample_base64.value\n                    elif model_type in [DateDatatype]:\n                        model_dict[field] = sample_date_value\n                    # Hacking here:\n                    # Root models should ideally not exist, however, sometimes we are stuck with them.\n                    # If that is the case we need sufficient information on the type in order to generate a model.\n                    # E.g. we need the type of the container.\n                    elif field == '__root__' and hasattr(model, '__name__'):\n                        model_dict[field] = generate_sample_value_by_type(\n                            outer_type, str_utils.classname_to_alias(model.__name__, AliasMode.FIELD)\n                        )\n                    else:\n                        model_dict[field] = generate_sample_value_by_type(outer_type, field)\n        # Note: this assumes list constrains in oscal are always 1 as a minimum size. if two this may still fail.\n    else:\n        if model_type is list:\n            return [generate_sample_value_by_type(model, '')]  # type: ignore\n        if model_type is dict:\n            return {const.REPLACE_ME: generate_sample_value_by_type(model, '')}  # type: ignore\n        raise err.TrestleError('Unhandled collection type.')\n    if model_type is list:\n        return [model(**model_dict)]  # type: ignore\n    if model_type is dict:\n        return {const.REPLACE_ME: model(**model_dict)}  # type: ignore\n    return model(**model_dict)  # type: ignore\n
                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.generate_sample_value_by_type","title":"generate_sample_value_by_type(type_, field_name)","text":"

                                    Given a type, return sample value.

                                    Includes the Optional use of passing down a parent_model

                                    Source code in trestle/core/generators.py
                                    def generate_sample_value_by_type(\n    type_: type,\n    field_name: str,\n) -> Union[datetime, bool, int, str, float, Enum]:\n\"\"\"Given a type, return sample value.\n\n    Includes the Optional use of passing down a parent_model\n    \"\"\"\n    # FIXME: Should be in separate generator module as it inherits EVERYTHING\n    if is_enum_method(type_):\n        return sample_method\n    if is_enum_task_valid_value(type_):\n        return sample_task_valid_value\n    if is_enum_observation_type_valid_value(type_):\n        return sample_observation_type_valid_value\n    if type_ is Base64:\n        return sample_base64\n    if type_ is datetime:\n        return datetime.now().astimezone()\n    if type_ is bool:\n        return False\n    if type_ is int:\n        return 0\n    if type_ is float:\n        return 0.00\n    if safe_is_sub(type_, ConstrainedStr) or (hasattr(type_, '__name__') and 'ConstrainedStr' in type_.__name__):\n        # This code here is messy. we need to meet a set of constraints. If we do\n        # TODO: handle regex directly\n        if 'uuid' == field_name:\n            return str(uuid.uuid4())\n        # some things like location_uuid in lists arrive here with field_name=''\n        if type_.regex and type_.regex.pattern.startswith('^[0-9A-Fa-f]{8}'):  # type: ignore\n            return const.SAMPLE_UUID_STR\n        if field_name == 'date_authorized':\n            return str(date.today().isoformat())\n        if field_name == 'oscal_version':\n            return OSCAL_VERSION\n        if 'uuid' in field_name:\n            return const.SAMPLE_UUID_STR\n        # Only case where are UUID is required but not in name.\n        if field_name.rstrip('s') == 'member_of_organization':\n            return const.SAMPLE_UUID_STR\n        return const.REPLACE_ME\n    if hasattr(type_, '__name__') and 'ConstrainedIntValue' in type_.__name__:\n        # create an int value as close to the floor as possible does not test upper bound\n        multiple = type_.multiple_of if type_.multiple_of else 1  # type: ignore # default to every integer\n        # this command is a bit of a problem\n        floor = type_.ge if type_.ge else 0  # type: ignore\n        floor = type_.gt + 1 if type_.gt else floor  # type: ignore\n        if math.remainder(floor, multiple) == 0:\n            return floor\n        return (floor + 1) * multiple\n    if safe_is_sub(type_, Enum):\n        # keys and values diverge due to hypens in oscal names\n        return type_(list(type_.__members__.values())[0])  # type: ignore\n    if type_ is str:\n        if field_name == 'oscal_version':\n            return OSCAL_VERSION\n        return const.REPLACE_ME\n    if type_ is pydantic.v1.networks.EmailStr:\n        return pydantic.v1.networks.EmailStr('dummy@sample.com')\n    if type_ is pydantic.v1.networks.AnyUrl:\n        # TODO: Cleanup: this should be usable from a url.. but it's not inuitive.\n        return pydantic.v1.networks.AnyUrl('https://sample.com/replaceme.html', scheme='http', host='sample.com')\n    if type_ is list:\n        raise err.TrestleError(f'Unable to generate sample for type {type_}')\n    # default to empty dict for anything else\n    return {}  # type: ignore\n
                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_by_type","title":"is_by_type(model_type)","text":"

                                    Check for by type.

                                    Source code in trestle/core/generators.py
                                    def is_by_type(model_type: Union[Type[TG], List[TG], Dict[str, TG]]) -> bool:\n\"\"\"Check for by type.\"\"\"\n    rval = False\n    if model_type == type_base64:\n        rval = True\n    return rval\n
                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_enum_method","title":"is_enum_method(type_)","text":"

                                    Test for method.

                                    Source code in trestle/core/generators.py
                                    def is_enum_method(type_: type) -> bool:\n\"\"\"Test for method.\"\"\"\n    rval = False\n    if utils.get_origin(type_) == Union:\n        args = typing.get_args(type_)\n        for arg in args:\n            if \"<enum 'Methods'>\" == f'{arg}':\n                rval = True\n                break\n    return rval\n
                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_enum_observation_type_valid_value","title":"is_enum_observation_type_valid_value(type_)","text":"

                                    Test for observation type valid value.

                                    Source code in trestle/core/generators.py
                                    def is_enum_observation_type_valid_value(type_: type) -> bool:\n\"\"\"Test for observation type valid value.\"\"\"\n    rval = False\n    if utils.get_origin(type_) == Union:\n        args = typing.get_args(type_)\n        for arg in args:\n            if \"<enum 'ObservationTypeValidValues'>\" == f'{arg}':\n                rval = True\n                break\n    return rval\n
                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_enum_task_valid_value","title":"is_enum_task_valid_value(type_)","text":"

                                    Test for task valid value.

                                    Source code in trestle/core/generators.py
                                    def is_enum_task_valid_value(type_: type) -> bool:\n\"\"\"Test for task valid value.\"\"\"\n    rval = False\n    if utils.get_origin(type_) == Union:\n        args = typing.get_args(type_)\n        for arg in args:\n            if \"<enum 'TaskValidValues'>\" == f'{arg}':\n                rval = True\n                break\n    return rval\n
                                    "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.safe_is_sub","title":"safe_is_sub(sub, parent)","text":"

                                    Is this a subclass of parent.

                                    Source code in trestle/core/generators.py
                                    def safe_is_sub(sub: Any, parent: Any) -> bool:\n\"\"\"Is this a subclass of parent.\"\"\"\n    is_class = inspect.isclass(sub)\n    return is_class and issubclass(sub, parent)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/","title":"generic_oscal","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal","title":"trestle.core.generic_oscal","text":"

                                    Generic classes to support both SSP and DefinedComponents.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.IMPLEMENTED_REQUIREMENTS","title":"IMPLEMENTED_REQUIREMENTS","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent","title":" GenericByComponent (TrestleBaseModel) pydantic-model","text":"

                                    Generic ByComponent for SSP and DefinedComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    class GenericByComponent(TrestleBaseModel):\n\"\"\"Generic ByComponent for SSP and DefinedComponent.\"\"\"\n\n    # only in SSP\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003\n    ) = Field(\n        ...,\n        alias='component_uuid',\n        description='A machine-oriented identifier reference to the component that is implemeting a given control.',\n        title='Component Universally Unique Identifier Reference',\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='By-Component Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description=  # noqa E251\n        'An implementation statement that describes how a control or a control statement is implemented within the referenced system component.',  # noqa E501\n        title='Control Implementation Description',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[GenericSetParameter]] = Field(None, alias='set-parameters')\n    implementation_status: Optional[common.ImplementationStatus] = Field(None, alias='implementation-status')\n    # removed export, inherited, satisfied\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n\n    @staticmethod\n    def generate() -> GenericByComponent:\n\"\"\"Generate instance of generic ByComponent.\"\"\"\n        uuid = str(uuid4())\n        return GenericByComponent(component_uuid=const.SAMPLE_UUID_STR, uuid=uuid, description='')\n\n    def as_ssp(self) -> ossp.ByComponent:\n\"\"\"Convert to ssp format.\"\"\"\n        set_params = []\n        for set_param in as_list(self.set_parameters):\n            new_set_param = ossp.SetParameter(\n                param_id=set_param.param_id, values=set_param.values, remarks=set_param.remarks\n            )\n            set_params.append(new_set_param)\n        set_params = none_if_empty(set_params)\n        return ossp.ByComponent(\n            component_uuid=self.component_uuid,\n            uuid=self.uuid,\n            description=self.description,\n            props=self.props,\n            links=self.links,\n            set_parameters=set_params,\n            implementation_status=self.implementation_status,\n            responsible_roles=self.responsible_roles\n        )\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to the component that is implemeting a given control.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.description","title":"description: str pydantic-field required","text":"

                                    An implementation statement that describes how a control or a control statement is implemented within the referenced system component.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.implementation_status","title":"implementation_status: ImplementationStatus pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.set_parameters","title":"set_parameters: Optional[List[GenericSetParameter]] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.as_ssp","title":"as_ssp(self)","text":"

                                    Convert to ssp format.

                                    Source code in trestle/core/generic_oscal.py
                                    def as_ssp(self) -> ossp.ByComponent:\n\"\"\"Convert to ssp format.\"\"\"\n    set_params = []\n    for set_param in as_list(self.set_parameters):\n        new_set_param = ossp.SetParameter(\n            param_id=set_param.param_id, values=set_param.values, remarks=set_param.remarks\n        )\n        set_params.append(new_set_param)\n    set_params = none_if_empty(set_params)\n    return ossp.ByComponent(\n        component_uuid=self.component_uuid,\n        uuid=self.uuid,\n        description=self.description,\n        props=self.props,\n        links=self.links,\n        set_parameters=set_params,\n        implementation_status=self.implementation_status,\n        responsible_roles=self.responsible_roles\n    )\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.generate","title":"generate() staticmethod","text":"

                                    Generate instance of generic ByComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    @staticmethod\ndef generate() -> GenericByComponent:\n\"\"\"Generate instance of generic ByComponent.\"\"\"\n    uuid = str(uuid4())\n    return GenericByComponent(component_uuid=const.SAMPLE_UUID_STR, uuid=uuid, description='')\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent","title":" GenericComponent (TrestleBaseModel) pydantic-model","text":"

                                    Generic component for SSP SystemComponent and DefinedComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    class GenericComponent(TrestleBaseModel):\n\"\"\"Generic component for SSP SystemComponent and DefinedComponent.\"\"\"\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='Component Identifier',\n    )\n    type: constr(regex=r'^\\S(.*\\S)?$') = Field(  # noqa A003 F722\n        ...,\n        description='A category describing the purpose of the component.',\n        title='Component Type',\n    )\n    title: str = Field(\n        ...,\n        description='A human readable name for the component.',\n        title='Component Title',\n    )\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description',\n    )\n    purpose: Optional[str] = Field(\n        None,\n        description='A summary of the technological or business purpose of the component.',\n        title='Purpose',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    protocols: Optional[List[common.Protocol]] = Field(None)\n    # ssp does not have a list of ci's but it does have one ci\n    control_implementations: Optional[List[GenericControlImplementation]] = Field(None, alias='control-implementations')\n    remarks: Optional[str] = None\n    # ssp has\n    status: common.ImplementationStatus\n\n    def as_defined_component(self) -> comp.DefinedComponent:\n\"\"\"Convert to DefinedComponent.\"\"\"\n        status = self.status\n        class_dict = copy.deepcopy(self.__dict__)\n        class_dict.pop('status', None)\n        def_comp = comp.DefinedComponent(**class_dict)\n        ControlInterface.insert_status_in_props(def_comp, status)\n        return def_comp\n\n    @classmethod\n    def from_defined_component(cls, def_comp: comp.DefinedComponent) -> GenericComponent:\n\"\"\"Convert defined component to generic.\"\"\"\n        status = ControlInterface.get_status_from_props(def_comp)\n        class_dict = copy.deepcopy(def_comp.__dict__)\n        if 'control_implementations' in class_dict:\n            new_cis = []\n            for ci in class_dict['control_implementations']:\n                new_cis.append(GenericControlImplementation.from_component_ci(ci))\n            class_dict['control-implementations'] = new_cis\n            class_dict.pop('control_implementations', None)\n        class_dict['status'] = status\n        return cls(**class_dict)\n\n    def as_system_component(self, status_override: str = '') -> ossp.SystemComponent:\n\"\"\"Convert to SystemComponent.\"\"\"\n        class_dict = copy.deepcopy(self.__dict__)\n        class_dict.pop('control_implementations', None)\n        status_str = self.status.state if self.status else const.STATUS_OPERATIONAL\n        status_str = status_override if status_override else status_str\n        if status_str not in ['under-development', 'operational', 'disposition', 'other']:\n            logger.warning(\n                f'SystemComponent status {status_str} not recognized.  Setting to {const.STATUS_OPERATIONAL}'\n            )\n            status_str = const.STATUS_OPERATIONAL\n        class_dict['status'] = ossp.Status(state=status_str, remarks=self.status.remarks)\n        return ossp.SystemComponent(**class_dict)\n\n    @staticmethod\n    def generate() -> GenericComponent:\n\"\"\"Generate instance of GenericComponent.\"\"\"\n        uuid = str(uuid4())\n        status = common.ImplementationStatus(state=const.STATUS_OPERATIONAL)\n        return GenericComponent(uuid=uuid, type=const.REPLACE_ME, title='', description='', status=status)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.control_implementations","title":"control_implementations: List[trestle.core.generic_oscal.GenericControlImplementation] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.description","title":"description: str pydantic-field required","text":"

                                    A description of the component, including information about its function.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.protocols","title":"protocols: List[trestle.oscal.common.Protocol] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.purpose","title":"purpose: str pydantic-field","text":"

                                    A summary of the technological or business purpose of the component.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.status","title":"status: ImplementationStatus pydantic-field required","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.title","title":"title: str pydantic-field required","text":"

                                    A human readable name for the component.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.type","title":"type: ConstrainedStrValue pydantic-field required","text":"

                                    A category describing the purpose of the component.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.as_defined_component","title":"as_defined_component(self)","text":"

                                    Convert to DefinedComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    def as_defined_component(self) -> comp.DefinedComponent:\n\"\"\"Convert to DefinedComponent.\"\"\"\n    status = self.status\n    class_dict = copy.deepcopy(self.__dict__)\n    class_dict.pop('status', None)\n    def_comp = comp.DefinedComponent(**class_dict)\n    ControlInterface.insert_status_in_props(def_comp, status)\n    return def_comp\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.as_system_component","title":"as_system_component(self, status_override='')","text":"

                                    Convert to SystemComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    def as_system_component(self, status_override: str = '') -> ossp.SystemComponent:\n\"\"\"Convert to SystemComponent.\"\"\"\n    class_dict = copy.deepcopy(self.__dict__)\n    class_dict.pop('control_implementations', None)\n    status_str = self.status.state if self.status else const.STATUS_OPERATIONAL\n    status_str = status_override if status_override else status_str\n    if status_str not in ['under-development', 'operational', 'disposition', 'other']:\n        logger.warning(\n            f'SystemComponent status {status_str} not recognized.  Setting to {const.STATUS_OPERATIONAL}'\n        )\n        status_str = const.STATUS_OPERATIONAL\n    class_dict['status'] = ossp.Status(state=status_str, remarks=self.status.remarks)\n    return ossp.SystemComponent(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.from_defined_component","title":"from_defined_component(def_comp) classmethod","text":"

                                    Convert defined component to generic.

                                    Source code in trestle/core/generic_oscal.py
                                    @classmethod\ndef from_defined_component(cls, def_comp: comp.DefinedComponent) -> GenericComponent:\n\"\"\"Convert defined component to generic.\"\"\"\n    status = ControlInterface.get_status_from_props(def_comp)\n    class_dict = copy.deepcopy(def_comp.__dict__)\n    if 'control_implementations' in class_dict:\n        new_cis = []\n        for ci in class_dict['control_implementations']:\n            new_cis.append(GenericControlImplementation.from_component_ci(ci))\n        class_dict['control-implementations'] = new_cis\n        class_dict.pop('control_implementations', None)\n    class_dict['status'] = status\n    return cls(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.generate","title":"generate() staticmethod","text":"

                                    Generate instance of GenericComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    @staticmethod\ndef generate() -> GenericComponent:\n\"\"\"Generate instance of GenericComponent.\"\"\"\n    uuid = str(uuid4())\n    status = common.ImplementationStatus(state=const.STATUS_OPERATIONAL)\n    return GenericComponent(uuid=uuid, type=const.REPLACE_ME, title='', description='', status=status)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation","title":" GenericControlImplementation (TrestleBaseModel) pydantic-model","text":"

                                    Generic control implementation for SSP and CompDef.

                                    Source code in trestle/core/generic_oscal.py
                                    class GenericControlImplementation(TrestleBaseModel):\n\"\"\"Generic control implementation for SSP and CompDef.\"\"\"\n\n    # not in ssp\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a set of implemented controls elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation set can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='Control Implementation Set Identifier',\n    )\n    # not in ssp\n    source: str = Field(\n        ...,\n        description=  # noqa E251\n        'A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.',  # noqa E501\n        title='Source Resource Reference',\n    )\n    description: str = Field(\n        ...,\n        description=  # noqa E251\n        'A description of how the specified set of controls are implemented for the containing component or capability.',  # noqa E501\n        title='Control Implementation Description',\n    )\n    # not in ssp\n    props: Optional[List[common.Property]] = Field(None)\n    # not in ssp\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[GenericSetParameter]] = Field(None, alias='set-parameters')\n    implemented_requirements: List[GenericImplementedRequirement] = Field(..., alias='implemented-requirements')\n\n    @staticmethod\n    def generate() -> GenericControlImplementation:\n\"\"\"Generate instance of this class.\"\"\"\n        uuid = str(uuid4())\n        imp_reqs = [GenericImplementedRequirement.generate()]\n        class_dict = {\n            'uuid': uuid,\n            'control-id': const.REPLACE_ME,\n            'source': const.REPLACE_ME,\n            'description': '',\n            'implemented-requirements': imp_reqs\n        }\n        return GenericControlImplementation(**class_dict)\n\n    @classmethod\n    def from_component_ci(cls, control_imp: comp.ControlImplementation) -> GenericControlImplementation:\n\"\"\"Convert component control imp to generic.\"\"\"\n        class_dict = copy.deepcopy(control_imp.__dict__)\n        if IMPLEMENTED_REQUIREMENTS in class_dict:\n            new_irs = []\n            ir_list = class_dict.get(IMPLEMENTED_REQUIREMENTS, None)\n            for ir in as_list(ir_list):\n                new_ir = GenericImplementedRequirement.from_comp_def(ir)\n                new_irs.append(new_ir)\n            class_dict['implemented-requirements'] = none_if_empty(new_irs)\n            class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n            new_sps = []\n            sp_list = class_dict.get('set_parameters', None)\n            for sp in as_list(sp_list):\n                new_sps.append(GenericSetParameter.from_defined_component(sp))\n            class_dict['set-parameters'] = none_if_empty(new_sps)\n            class_dict.pop('set_parameters', None)\n\n        return cls(**class_dict)\n\n    def as_ssp(self) -> ossp.ControlImplementation:\n\"\"\"Represent in ssp form.\"\"\"\n        imp_reqs = []\n        for imp_req in self.implemented_requirements:\n            imp_reqs.append(imp_req.as_ssp())\n        class_dict = self.__dict__\n        for prop in ['uuid', 'source', 'props', 'links', IMPLEMENTED_REQUIREMENTS]:\n            class_dict.pop(prop, None)\n        if imp_reqs:\n            class_dict['implemented-requirements'] = imp_reqs\n            class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n        return ossp.ControlImplementation(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.description","title":"description: str pydantic-field required","text":"

                                    A description of how the specified set of controls are implemented for the containing component or capability.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.implemented_requirements","title":"implemented_requirements: List[trestle.core.generic_oscal.GenericImplementedRequirement] pydantic-field required","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.set_parameters","title":"set_parameters: List[trestle.core.generic_oscal.GenericSetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.source","title":"source: str pydantic-field required","text":"

                                    A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a set of implemented controls elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation set can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.as_ssp","title":"as_ssp(self)","text":"

                                    Represent in ssp form.

                                    Source code in trestle/core/generic_oscal.py
                                    def as_ssp(self) -> ossp.ControlImplementation:\n\"\"\"Represent in ssp form.\"\"\"\n    imp_reqs = []\n    for imp_req in self.implemented_requirements:\n        imp_reqs.append(imp_req.as_ssp())\n    class_dict = self.__dict__\n    for prop in ['uuid', 'source', 'props', 'links', IMPLEMENTED_REQUIREMENTS]:\n        class_dict.pop(prop, None)\n    if imp_reqs:\n        class_dict['implemented-requirements'] = imp_reqs\n        class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n    return ossp.ControlImplementation(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.from_component_ci","title":"from_component_ci(control_imp) classmethod","text":"

                                    Convert component control imp to generic.

                                    Source code in trestle/core/generic_oscal.py
                                    @classmethod\ndef from_component_ci(cls, control_imp: comp.ControlImplementation) -> GenericControlImplementation:\n\"\"\"Convert component control imp to generic.\"\"\"\n    class_dict = copy.deepcopy(control_imp.__dict__)\n    if IMPLEMENTED_REQUIREMENTS in class_dict:\n        new_irs = []\n        ir_list = class_dict.get(IMPLEMENTED_REQUIREMENTS, None)\n        for ir in as_list(ir_list):\n            new_ir = GenericImplementedRequirement.from_comp_def(ir)\n            new_irs.append(new_ir)\n        class_dict['implemented-requirements'] = none_if_empty(new_irs)\n        class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n        new_sps = []\n        sp_list = class_dict.get('set_parameters', None)\n        for sp in as_list(sp_list):\n            new_sps.append(GenericSetParameter.from_defined_component(sp))\n        class_dict['set-parameters'] = none_if_empty(new_sps)\n        class_dict.pop('set_parameters', None)\n\n    return cls(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.generate","title":"generate() staticmethod","text":"

                                    Generate instance of this class.

                                    Source code in trestle/core/generic_oscal.py
                                    @staticmethod\ndef generate() -> GenericControlImplementation:\n\"\"\"Generate instance of this class.\"\"\"\n    uuid = str(uuid4())\n    imp_reqs = [GenericImplementedRequirement.generate()]\n    class_dict = {\n        'uuid': uuid,\n        'control-id': const.REPLACE_ME,\n        'source': const.REPLACE_ME,\n        'description': '',\n        'implemented-requirements': imp_reqs\n    }\n    return GenericControlImplementation(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement","title":" GenericImplementedRequirement (TrestleBaseModel) pydantic-model","text":"

                                    Generic ImplementedRequirement for SSP and DefinedComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    class GenericImplementedRequirement(TrestleBaseModel):\n\"\"\"Generic ImplementedRequirement for SSP and DefinedComponent.\"\"\"\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a specific control implementation elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='Control Implementation Identifier',\n    )\n    control_id: constr(\n        regex=  # noqa E251\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'  # noqa E501\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=  # noqa E251\n        'A human-oriented identifier reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',  # noqa E501\n        title='Control Identifier Reference',\n    )\n    # only compdef has description\n    description: str = Field(\n        ...,\n        description=  # noqa E251\n        'A description of how the specified control is implemented for the containing component or capability.',  # noqa E501\n        title='Control Implementation Description',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[GenericSetParameter]] = Field(None, alias='set-parameters')\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    statements: Optional[List[GenericStatement]] = Field(None)\n    remarks: Optional[str] = None\n    # ssp has following\n    by_components: Optional[List[GenericByComponent]] = Field(None, alias='by-components')\n\n    @staticmethod\n    def generate() -> GenericImplementedRequirement:\n\"\"\"Generate instance of this class.\"\"\"\n        uuid = str(uuid4())\n        class_dict = {'uuid': uuid, 'control-id': const.REPLACE_ME, 'description': ''}\n        return GenericImplementedRequirement(**class_dict)\n\n    @classmethod\n    def from_comp_def(cls, imp_req: comp.ImplementedRequirement) -> GenericImplementedRequirement:\n\"\"\"Convert component form of imp req to generic.\"\"\"\n        class_dict = copy.deepcopy(imp_req.__dict__)\n        class_dict['control-id'] = class_dict.pop('control_id', None)\n        return cls(**class_dict)\n\n    def as_ssp(self) -> ossp.ImplementedRequirement:\n\"\"\"Convert to ssp form.\"\"\"\n        class_dict = copy.deepcopy(self.__dict__)\n        del class_dict['description']\n        new_stat_list = []\n        for statement in as_list(self.statements):\n            new_stat_list.append(statement.as_ssp())\n        if new_stat_list:\n            class_dict['statements'] = new_stat_list\n        return ossp.ImplementedRequirement(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.by_components","title":"by_components: List[trestle.core.generic_oscal.GenericByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented identifier reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.description","title":"description: str pydantic-field required","text":"

                                    A description of how the specified control is implemented for the containing component or capability.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.set_parameters","title":"set_parameters: List[trestle.core.generic_oscal.GenericSetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.statements","title":"statements: List[trestle.core.generic_oscal.GenericStatement] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a specific control implementation elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.as_ssp","title":"as_ssp(self)","text":"

                                    Convert to ssp form.

                                    Source code in trestle/core/generic_oscal.py
                                    def as_ssp(self) -> ossp.ImplementedRequirement:\n\"\"\"Convert to ssp form.\"\"\"\n    class_dict = copy.deepcopy(self.__dict__)\n    del class_dict['description']\n    new_stat_list = []\n    for statement in as_list(self.statements):\n        new_stat_list.append(statement.as_ssp())\n    if new_stat_list:\n        class_dict['statements'] = new_stat_list\n    return ossp.ImplementedRequirement(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.from_comp_def","title":"from_comp_def(imp_req) classmethod","text":"

                                    Convert component form of imp req to generic.

                                    Source code in trestle/core/generic_oscal.py
                                    @classmethod\ndef from_comp_def(cls, imp_req: comp.ImplementedRequirement) -> GenericImplementedRequirement:\n\"\"\"Convert component form of imp req to generic.\"\"\"\n    class_dict = copy.deepcopy(imp_req.__dict__)\n    class_dict['control-id'] = class_dict.pop('control_id', None)\n    return cls(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.generate","title":"generate() staticmethod","text":"

                                    Generate instance of this class.

                                    Source code in trestle/core/generic_oscal.py
                                    @staticmethod\ndef generate() -> GenericImplementedRequirement:\n\"\"\"Generate instance of this class.\"\"\"\n    uuid = str(uuid4())\n    class_dict = {'uuid': uuid, 'control-id': const.REPLACE_ME, 'description': ''}\n    return GenericImplementedRequirement(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter","title":" GenericSetParameter (TrestleBaseModel) pydantic-model","text":"

                                    Generic SetParameter for SSP and DefinedComponent.

                                    Source code in trestle/core/generic_oscal.py
                                    class GenericSetParameter(TrestleBaseModel):\n\"\"\"Generic SetParameter for SSP and DefinedComponent.\"\"\"\n\n    param_id: constr(\n        regex=  # noqa E251\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'  # noqa E501\n    ) = Field(\n        ...,\n        alias='param-id',\n        description=  # noqa E251\n        \"A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.\",  # noqa E501\n        title='Parameter ID',\n    )\n    values: List[str] = Field(...)\n    remarks: Optional[str] = None\n\n    @staticmethod\n    def from_defined_component(sp: comp.SetParameter):\n\"\"\"Generate generic set parameter from comp_def version.\"\"\"\n        class_dict = {'param-id': sp.param_id, 'values': sp.values, 'remarks': sp.remarks}\n        return GenericSetParameter(**class_dict)\n\n    def to_ssp(self):\n\"\"\"Convert to ssp format.\"\"\"\n        return (ossp.SetParameter(param_id=self.param_id, values=self.values, remarks=self.remarks))\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.values","title":"values: List[str] pydantic-field required","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.from_defined_component","title":"from_defined_component(sp) staticmethod","text":"

                                    Generate generic set parameter from comp_def version.

                                    Source code in trestle/core/generic_oscal.py
                                    @staticmethod\ndef from_defined_component(sp: comp.SetParameter):\n\"\"\"Generate generic set parameter from comp_def version.\"\"\"\n    class_dict = {'param-id': sp.param_id, 'values': sp.values, 'remarks': sp.remarks}\n    return GenericSetParameter(**class_dict)\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.to_ssp","title":"to_ssp(self)","text":"

                                    Convert to ssp format.

                                    Source code in trestle/core/generic_oscal.py
                                    def to_ssp(self):\n\"\"\"Convert to ssp format.\"\"\"\n    return (ossp.SetParameter(param_id=self.param_id, values=self.values, remarks=self.remarks))\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement","title":" GenericStatement (TrestleBaseModel) pydantic-model","text":"

                                    Generic statement for SSP and DefinedComp.

                                    Source code in trestle/core/generic_oscal.py
                                    class GenericStatement(TrestleBaseModel):\n\"\"\"Generic statement for SSP and DefinedComp.\"\"\"\n\n    statement_id: constr(\n        regex=  # noqa E251\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'  # noqa FS003 E501\n    ) = Field(\n        ...,\n        alias='statement_id',\n        description='A human-oriented identifier reference to a control statement.',\n        title='Control Statement Reference',\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).',  # noqa E501\n        title='Control Statement Reference Universally Unique Identifier',\n    )\n    # this is not in ssp statement\n    description: str = Field(\n        ...,\n        description='A summary of how the containing control statement is implemented by the component or capability.',\n        title='Statement Implementation Description',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n    # ssp has following\n    by_components: Optional[List[GenericByComponent]] = Field(None, alias='by-components')\n\n    def as_ssp(self) -> ossp.Statement:\n\"\"\"Represent in ssp form.\"\"\"\n        class_dict = copy.deepcopy(self.__dict__)\n        class_dict.pop('description', None)\n        by_comps = []\n        for by_comp in as_list(self.by_components):\n            new_by_comp = by_comp.as_ssp()\n            by_comps.append(new_by_comp)\n        return ossp.Statement(\n            statement_id=self.statement_id,\n            uuid=self.uuid,\n            props=self.props,\n            links=self.links,\n            responsible_roles=self.responsible_roles,\n            by_components=by_comps,\n            remarks=self.remarks\n        )\n
                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.by_components","title":"by_components: List[trestle.core.generic_oscal.GenericByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.description","title":"description: str pydantic-field required","text":"

                                    A summary of how the containing control statement is implemented by the component or capability.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.statement_id","title":"statement_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented identifier reference to a control statement.

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).

                                    "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.as_ssp","title":"as_ssp(self)","text":"

                                    Represent in ssp form.

                                    Source code in trestle/core/generic_oscal.py
                                    def as_ssp(self) -> ossp.Statement:\n\"\"\"Represent in ssp form.\"\"\"\n    class_dict = copy.deepcopy(self.__dict__)\n    class_dict.pop('description', None)\n    by_comps = []\n    for by_comp in as_list(self.by_components):\n        new_by_comp = by_comp.as_ssp()\n        by_comps.append(new_by_comp)\n    return ossp.Statement(\n        statement_id=self.statement_id,\n        uuid=self.uuid,\n        props=self.props,\n        links=self.links,\n        responsible_roles=self.responsible_roles,\n        by_components=by_comps,\n        remarks=self.remarks\n    )\n
                                    "},{"location":"api_reference/trestle.core.jinja/","title":"jinja","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja","title":"trestle.core.jinja","text":"

                                    Trestle utilities to customize .

                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude","title":" MDCleanInclude (TrestleJinjaExtension) ","text":"

                                    Inject the parameter of the tag as the resulting content.

                                    Source code in trestle/core/jinja.py
                                    class MDCleanInclude(TrestleJinjaExtension):\n\"\"\"Inject the parameter of the tag as the resulting content.\"\"\"\n\n    tags = {'md_clean_include'}\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n        kwargs = None\n        expected_heading_level = None\n        count = 0\n        while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n            count = count + 1\n            if count > self.max_tag_parse:\n                raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n            token = parser.stream.current\n            if token.test('name:md_clean_include'):\n                parser.stream.expect(lexer.TOKEN_NAME)\n                markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n            elif kwargs is not None:\n                arg = token.value\n                next(parser.stream)\n                parser.stream.expect(lexer.TOKEN_ASSIGN)\n                token = parser.stream.current\n                exp = self.parse_expression(parser)\n                kwargs[arg] = exp.value\n            else:\n                if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                    kwargs = {}\n                continue\n        md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n        fm = frontmatter.loads(md_content)\n        content = fm.content\n        content += '\\n\\n'\n        if kwargs is not None:\n            expected_heading_level = kwargs.get('heading_level')\n        if expected_heading_level is not None:\n            content = adjust_heading_level(content, expected_heading_level)\n\n        local_parser = Parser(self.environment, content)\n        top_level_output = local_parser.parse()\n\n        return top_level_output.body\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.tags","title":"tags: Set[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.__init__","title":"__init__(self, environment) special","text":"Source code in trestle/core/jinja.py
                                    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.parse","title":"parse(self, parser)","text":"

                                    Execute parsing of md token and return nodes.

                                    Source code in trestle/core/jinja.py
                                    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n    kwargs = None\n    expected_heading_level = None\n    count = 0\n    while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n        count = count + 1\n        if count > self.max_tag_parse:\n            raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n        token = parser.stream.current\n        if token.test('name:md_clean_include'):\n            parser.stream.expect(lexer.TOKEN_NAME)\n            markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n        elif kwargs is not None:\n            arg = token.value\n            next(parser.stream)\n            parser.stream.expect(lexer.TOKEN_ASSIGN)\n            token = parser.stream.current\n            exp = self.parse_expression(parser)\n            kwargs[arg] = exp.value\n        else:\n            if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                kwargs = {}\n            continue\n    md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n    fm = frontmatter.loads(md_content)\n    content = fm.content\n    content += '\\n\\n'\n    if kwargs is not None:\n        expected_heading_level = kwargs.get('heading_level')\n    if expected_heading_level is not None:\n        content = adjust_heading_level(content, expected_heading_level)\n\n    local_parser = Parser(self.environment, content)\n    top_level_output = local_parser.parse()\n\n    return top_level_output.body\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp","title":" MDDatestamp (TrestleJinjaExtension) ","text":"

                                    Inject the parameter of the tag as the resulting content.

                                    Source code in trestle/core/jinja.py
                                    class MDDatestamp(TrestleJinjaExtension):\n\"\"\"Inject the parameter of the tag as the resulting content.\"\"\"\n\n    tags = {'md_datestamp'}\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n        kwargs = None\n        count = 0\n        while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n            count = count + 1\n            token = parser.stream.current\n            if count > self.max_tag_parse:\n                raise err.TrestleError(f'Unexpected Jinja tag structure provided at token {token.value}')\n            if token.test('name:md_datestamp'):\n                parser.stream.expect(lexer.TOKEN_NAME)\n            elif kwargs is not None:\n                arg = token.value\n                next(parser.stream)\n                parser.stream.expect(lexer.TOKEN_ASSIGN)\n                token = parser.stream.current\n                exp = self.parse_expression(parser)\n                kwargs[arg] = exp.value\n            else:\n                if parser.stream.look().type == lexer.TOKEN_ASSIGN or parser.stream.look().type == lexer.TOKEN_STRING:\n                    kwargs = {}\n                continue\n\n        if kwargs is not None:\n            if 'format' in kwargs and type(kwargs['format'] is str):\n                date_string = date.today().strftime(kwargs['format'])\n            else:\n                date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT)\n            if 'newline' in kwargs and kwargs['newline'] is False:\n                pass\n            else:\n                date_string += '\\n\\n'\n        else:\n            date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT) + '\\n\\n'\n\n        local_parser = Parser(self.environment, date_string)\n        datestamp_output = local_parser.parse()\n\n        return datestamp_output.body\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.tags","title":"tags: Set[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.__init__","title":"__init__(self, environment) special","text":"Source code in trestle/core/jinja.py
                                    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.parse","title":"parse(self, parser)","text":"

                                    Execute parsing of md token and return nodes.

                                    Source code in trestle/core/jinja.py
                                    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n    kwargs = None\n    count = 0\n    while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n        count = count + 1\n        token = parser.stream.current\n        if count > self.max_tag_parse:\n            raise err.TrestleError(f'Unexpected Jinja tag structure provided at token {token.value}')\n        if token.test('name:md_datestamp'):\n            parser.stream.expect(lexer.TOKEN_NAME)\n        elif kwargs is not None:\n            arg = token.value\n            next(parser.stream)\n            parser.stream.expect(lexer.TOKEN_ASSIGN)\n            token = parser.stream.current\n            exp = self.parse_expression(parser)\n            kwargs[arg] = exp.value\n        else:\n            if parser.stream.look().type == lexer.TOKEN_ASSIGN or parser.stream.look().type == lexer.TOKEN_STRING:\n                kwargs = {}\n            continue\n\n    if kwargs is not None:\n        if 'format' in kwargs and type(kwargs['format'] is str):\n            date_string = date.today().strftime(kwargs['format'])\n        else:\n            date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT)\n        if 'newline' in kwargs and kwargs['newline'] is False:\n            pass\n        else:\n            date_string += '\\n\\n'\n    else:\n        date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT) + '\\n\\n'\n\n    local_parser = Parser(self.environment, date_string)\n    datestamp_output = local_parser.parse()\n\n    return datestamp_output.body\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude","title":" MDSectionInclude (TrestleJinjaExtension) ","text":"

                                    Inject the parameter of the tag as the resulting content.

                                    Source code in trestle/core/jinja.py
                                    class MDSectionInclude(TrestleJinjaExtension):\n\"\"\"Inject the parameter of the tag as the resulting content.\"\"\"\n\n    tags = {'mdsection_include'}\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n        kwargs = None\n        expected_heading_level = None\n        count = 0\n        while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n            count = count + 1\n            if count > self.max_tag_parse:\n                raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n            token = parser.stream.current\n            if token.test('name:mdsection_include'):\n                parser.stream.expect(lexer.TOKEN_NAME)\n                markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n                section_title = parser.stream.expect(lexer.TOKEN_STRING)\n            elif kwargs is not None:\n                arg = token.value\n                next(parser.stream)\n                parser.stream.expect(lexer.TOKEN_ASSIGN)\n                token = parser.stream.current\n                exp = self.parse_expression(parser)\n                kwargs[arg] = exp.value\n            else:\n                if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                    kwargs = {}\n                continue\n        # Use the established environment to source the file\n        md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n        fm = frontmatter.loads(md_content)\n        if not fm.metadata == {}:\n            logger.warning('Non zero metadata on MD section include - ignoring')\n        full_md = docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown(fm.content.split('\\n'))\n        md_section = full_md.get_node_for_key(section_title.value, strict_matching=True)\n        # adjust\n        if kwargs is not None:\n            expected_heading_level = kwargs.get('heading_level')\n        if expected_heading_level is not None:\n            level = md_section.get_node_header_lvl()\n            delta = int(expected_heading_level) - level\n            if not delta == 0:\n                md_section.change_header_level_by(delta)\n        if not md_section:\n            raise err.TrestleError(\n                f'Unable to retrieve section \"{section_title.value}\"\" from {markdown_source.value} jinja template.'\n            )\n        local_parser = Parser(self.environment, md_section.content.raw_text)\n        top_level_output = local_parser.parse()\n\n        return top_level_output.body\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.tags","title":"tags: Set[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.__init__","title":"__init__(self, environment) special","text":"Source code in trestle/core/jinja.py
                                    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.parse","title":"parse(self, parser)","text":"

                                    Execute parsing of md token and return nodes.

                                    Source code in trestle/core/jinja.py
                                    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n    kwargs = None\n    expected_heading_level = None\n    count = 0\n    while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n        count = count + 1\n        if count > self.max_tag_parse:\n            raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n        token = parser.stream.current\n        if token.test('name:mdsection_include'):\n            parser.stream.expect(lexer.TOKEN_NAME)\n            markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n            section_title = parser.stream.expect(lexer.TOKEN_STRING)\n        elif kwargs is not None:\n            arg = token.value\n            next(parser.stream)\n            parser.stream.expect(lexer.TOKEN_ASSIGN)\n            token = parser.stream.current\n            exp = self.parse_expression(parser)\n            kwargs[arg] = exp.value\n        else:\n            if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                kwargs = {}\n            continue\n    # Use the established environment to source the file\n    md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n    fm = frontmatter.loads(md_content)\n    if not fm.metadata == {}:\n        logger.warning('Non zero metadata on MD section include - ignoring')\n    full_md = docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown(fm.content.split('\\n'))\n    md_section = full_md.get_node_for_key(section_title.value, strict_matching=True)\n    # adjust\n    if kwargs is not None:\n        expected_heading_level = kwargs.get('heading_level')\n    if expected_heading_level is not None:\n        level = md_section.get_node_header_lvl()\n        delta = int(expected_heading_level) - level\n        if not delta == 0:\n            md_section.change_header_level_by(delta)\n    if not md_section:\n        raise err.TrestleError(\n            f'Unable to retrieve section \"{section_title.value}\"\" from {markdown_source.value} jinja template.'\n        )\n    local_parser = Parser(self.environment, md_section.content.raw_text)\n    top_level_output = local_parser.parse()\n\n    return top_level_output.body\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension","title":" TrestleJinjaExtension (Extension) ","text":"

                                    Class to define common methods to be inherited from for use in trestle.

                                    Source code in trestle/core/jinja.py
                                    class TrestleJinjaExtension(Extension):\n\"\"\"Class to define common methods to be inherited from for use in trestle.\"\"\"\n\n    # This\n    max_tag_parse = 20\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    @staticmethod\n    def parse_expression(parser):\n\"\"\"Safely parse jinja expression.\"\"\"\n        # Licensed under MIT from:\n        # https://github.com/MoritzS/jinja2-django-tags/blob/master/jdj_tags/extensions.py#L424\n        # Due to how the jinja2 parser works, it treats \"foo\" \"bar\" as a single\n        # string literal as it is the case in python.\n        # But the url tag in django supports multiple string arguments, e.g.\n        # \"{% url 'my_view' 'arg1' 'arg2' %}\".\n        # That's why we have to check if it's a string literal first.\n        token = parser.stream.current\n        if token.test(lexer.TOKEN_STRING):\n            expr = nodes.Const(token.value, lineno=token.lineno)\n            next(parser.stream)\n        else:\n            expr = parser.parse_expression(False)\n\n        return expr\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.max_tag_parse","title":"max_tag_parse","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.__init__","title":"__init__(self, environment) special","text":"

                                    Ensure enviroment is set and carried into class vars.

                                    Source code in trestle/core/jinja.py
                                    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.parse_expression","title":"parse_expression(parser) staticmethod","text":"

                                    Safely parse jinja expression.

                                    Source code in trestle/core/jinja.py
                                    @staticmethod\ndef parse_expression(parser):\n\"\"\"Safely parse jinja expression.\"\"\"\n    # Licensed under MIT from:\n    # https://github.com/MoritzS/jinja2-django-tags/blob/master/jdj_tags/extensions.py#L424\n    # Due to how the jinja2 parser works, it treats \"foo\" \"bar\" as a single\n    # string literal as it is the case in python.\n    # But the url tag in django supports multiple string arguments, e.g.\n    # \"{% url 'my_view' 'arg1' 'arg2' %}\".\n    # That's why we have to check if it's a string literal first.\n    token = parser.stream.current\n    if token.test(lexer.TOKEN_STRING):\n        expr = nodes.Const(token.value, lineno=token.lineno)\n        next(parser.stream)\n    else:\n        expr = parser.parse_expression(False)\n\n    return expr\n
                                    "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.adjust_heading_level","title":"adjust_heading_level(input_md, expected)","text":"

                                    Adjust the header level of a markdown string such that the most significant header matches the expected #'s.

                                    Source code in trestle/core/jinja.py
                                    def adjust_heading_level(input_md: str, expected: int) -> str:\n\"\"\"Adjust the header level of a markdown string such that the most significant header matches the expected #'s.\"\"\"\n    output_md = input_md\n    mdn = docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown(input_md.split('\\n'))\n    if mdn.subnodes:\n        mdn_top_heading = mdn.subnodes[0].get_node_header_lvl()\n        delta = int(expected) - mdn_top_heading\n        if not delta == 0:\n            mdn.change_header_level_by(delta)\n            output_md = mdn.content.raw_text\n    return output_md\n
                                    "},{"location":"api_reference/trestle.core.links_validator/","title":"links_validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator","title":"trestle.core.links_validator","text":"

                                    Validate catalog by confirming control links match resources in backmatter.

                                    "},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.LinksValidator","title":" LinksValidator (Validator) ","text":"

                                    Validator to confirm all uuids in links and prose match resources in backmatter.

                                    Source code in trestle/core/links_validator.py
                                    class LinksValidator(Validator):\n\"\"\"Validator to confirm all uuids in links and prose match resources in backmatter.\"\"\"\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            Always returns True, but gives warning if links and resources are not one-to-one.\n        \"\"\"\n        refs = ModelUtils.find_uuid_refs(model)\n\n        # find uuids in backmatter\n        links: List[str] = []\n        if model.back_matter and model.back_matter.resources:\n            links = [res.uuid for res in model.back_matter.resources]\n            seen: Set[str] = set()\n            dupes: List[str] = []\n            for uuid in links:\n                if uuid in seen:\n                    dupes.append(uuid)\n                else:\n                    seen.add(uuid)\n            if dupes:\n                if not quiet:\n                    logger.warning(f'Backmatter has  {len(dupes)} duplicate link uuids.')\n                logger.debug(f'Backmatter has {len(dupes)} duplicate link uuids: {dupes}')\n\n        links = set(links)\n        in_refs = refs.difference(links)\n        if in_refs:\n            if not quiet:\n                logger.warning(f'Model references {len(refs)} uuids and {len(in_refs)} of them are not in resources.')\n            logger.debug(f'Model references {len(in_refs)} uuids not in resources: {in_refs}')\n\n        in_links = links.difference(refs)\n        if in_links:\n            if not quiet:\n                logger.warning(f'Resources have {len(links)} uuids and {len(in_links)} are not referenced by model.')\n            logger.debug(f'Resources have {len(in_links)} uuids not referenced by model: {in_links}')\n\n        # This validator is intended just to give warnings, so it always returns True\n        return True\n
                                    "},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.LinksValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.LinksValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                    Test if the model is valid.

                                    Parameters:

                                    Name Type Description Default model ~TopLevelOscalModel

                                    A top level OSCAL model.

                                    required quiet bool

                                    Don't report msgs unless invalid.

                                    required

                                    Returns:

                                    Type Description bool

                                    Always returns True, but gives warning if links and resources are not one-to-one.

                                    Source code in trestle/core/links_validator.py
                                    def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        Always returns True, but gives warning if links and resources are not one-to-one.\n    \"\"\"\n    refs = ModelUtils.find_uuid_refs(model)\n\n    # find uuids in backmatter\n    links: List[str] = []\n    if model.back_matter and model.back_matter.resources:\n        links = [res.uuid for res in model.back_matter.resources]\n        seen: Set[str] = set()\n        dupes: List[str] = []\n        for uuid in links:\n            if uuid in seen:\n                dupes.append(uuid)\n            else:\n                seen.add(uuid)\n        if dupes:\n            if not quiet:\n                logger.warning(f'Backmatter has  {len(dupes)} duplicate link uuids.')\n            logger.debug(f'Backmatter has {len(dupes)} duplicate link uuids: {dupes}')\n\n    links = set(links)\n    in_refs = refs.difference(links)\n    if in_refs:\n        if not quiet:\n            logger.warning(f'Model references {len(refs)} uuids and {len(in_refs)} of them are not in resources.')\n        logger.debug(f'Model references {len(in_refs)} uuids not in resources: {in_refs}')\n\n    in_links = links.difference(refs)\n    if in_links:\n        if not quiet:\n            logger.warning(f'Resources have {len(links)} uuids and {len(in_links)} are not referenced by model.')\n        logger.debug(f'Resources have {len(in_links)} uuids not referenced by model: {in_links}')\n\n    # This validator is intended just to give warnings, so it always returns True\n    return True\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/","title":"base_markdown_node","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node","title":"trestle.core.markdown.base_markdown_node","text":"

                                    A base markdown node.

                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode","title":" BaseMarkdownNode ","text":"

                                    Markdown will be read to the tree.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    class BaseMarkdownNode:\n\"\"\"Markdown will be read to the tree.\"\"\"\n\n    def __init__(self, key: str, content: BaseSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n        self.subnodes: List[BaseMarkdownNode] = []\n        self.key = key\n        self.content = content\n        self.starting_line = starting_line\n\n    @classmethod\n    def build_tree_from_markdown(cls, lines: List[str]) -> BaseMarkdownNode:\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n        ob = cls.__new__(cls)\n        start_level = ob._get_max_header_lvl(lines)\n        ob, _ = ob._build_tree(lines, 'root', 0, start_level)\n        return ob\n\n    def get_all_headers_for_level(self, level: int) -> Iterable[str]:\n\"\"\"Return all headers per specified level of hierarchy.\"\"\"\n        return list(\n            filter(lambda header: self._get_header_level_if_valid(header) == level, self.content.subnodes_keys)\n        ).__iter__()\n\n    def get_node_for_key(self, key: str, strict_matching: bool = True) -> Optional[BaseMarkdownNode]:\n\"\"\"Return a first node for the given key, substring matching is supported. The method is case insensitive.\"\"\"\n        if not strict_matching:\n            if not any(key.lower() in el.lower() for el in self.content.subnodes_keys):\n                return None\n            elif len(as_filtered_list(self.content.subnodes_keys, lambda el: key.lower() in el.lower())) > 1:\n                logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n        else:\n            if key.lower() not in [el.lower() for el in self.content.subnodes_keys]:\n                return None\n            elif len(as_filtered_list(self.content.subnodes_keys, lambda el: el.lower() == key.lower())) > 1:\n                logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n\n        return self._rec_traverse(self, key, strict_matching)\n\n    def get_all_nodes_for_keys(\n        self,\n        keys: List[str],\n        strict_matching: bool = True,\n        stop_recurse_on_first_match: bool = False\n    ) -> List[BaseMarkdownNode]:\n\"\"\"\n        Return all nodes for the given keys, substring matching is supported.\n\n        Args:\n            keys: List of strings for the headers being collected\n            strict_matching: Force exact match of key with header vs. simple substring match\n            stop_recurse_on_first_match: Return first match of any of the keys and don't search subnodes\n\n        Returns: List of found markdown nodes\n        \"\"\"\n        if not strict_matching:\n            if not any(key in el for el in self.content.subnodes_keys for key in keys):\n                return []\n        elif not set(keys).intersection(self.content.subnodes_keys):\n            return []\n\n        return self._rec_traverse_all(self, keys, strict_matching, stop_recurse_on_first_match)\n\n    def get_all_headers_for_key(self, key: str, strict_matching: bool = True) -> Iterable[str]:\n\"\"\"Return all headers contained in the node with a given key.\"\"\"\n        if strict_matching:\n            return list(filter(lambda header: key == header, self.content.subnodes_keys)).__iter__()\n        else:\n            return list(filter(lambda header: key in header, self.content.subnodes_keys)).__iter__()\n\n    def get_node_header_lvl(self) -> Optional[int]:\n\"\"\"Return current node header level.\"\"\"\n        return self._get_header_level_if_valid(self.key)\n\n    def change_header_level_by(self, delta_level: int) -> None:\n\"\"\"\n        Change all headers in the tree by specified level up or down.\n\n        All children nodes will be modified by specified level as well.\n\n        Args:\n            delta_level: each header will be modified by this number, can be negative.\n        \"\"\"\n        # construct a map\n        header_map = {}\n        if self.key != 'root':\n            new_key = self._modify_header_level(self.key, delta_level)\n            header_map[self.key] = new_key\n        for key in self.content.subnodes_keys:\n            new_key = self._modify_header_level(key, delta_level)\n            header_map[key] = new_key\n\n        # go through all contents and modify headers\n        self._rec_traverse_header_update(self, header_map)\n\n    def delete_nodes_text(self, keys: List[str], strict_matching: bool = True) -> List[str]:\n\"\"\"Remove text from this node that is found in matching subnodes.\"\"\"\n        text_lines = self.content.raw_text.split('\\n')\n        matching_nodes = self.get_all_nodes_for_keys(keys, strict_matching, True)\n        # need to delete from end and proceed backwards\n        sorted_nodes = sorted(matching_nodes, key=lambda node: node.starting_line, reverse=True)\n        for node in sorted_nodes:\n            last_line = node.starting_line + len(node.content.raw_text.split('\\n'))\n            delete_list_from_list(text_lines, list(range(node.starting_line, last_line)))\n        return text_lines\n\n    @abstractmethod\n    def _build_tree(self, lines: List[str], root_key: str, starting_line: int,\n                    level: int) -> Tuple[BaseMarkdownNode, int]:\n\"\"\"Build a tree from the markdown recursively.\"\"\"\n        pass\n\n    def _modify_header_level(self, header: str, delta_level: int) -> str:\n\"\"\"Modify header level by specified level.\"\"\"\n        if delta_level == 0:\n            logger.debug('Nothing to modify in header, level 0 is given.')\n            return header\n\n        current_level = self._get_header_level_if_valid(header)\n        if current_level is None:\n            current_level = 0\n        if current_level + delta_level < 0:\n            logger.warning(\n                f'Cannot substract {delta_level} as level of {header} is {current_level}. All `#` will be removed.'\n            )\n            delta_level = current_level * -1\n\n        if current_level + delta_level == 0:\n            replacement = ''\n        else:\n            replacement = '#' * (current_level + delta_level)\n        header = header.replace('#' * current_level, replacement)\n\n        return header.strip(' ')\n\n    def _get_header_level_if_valid(self, line: str) -> Optional[int]:\n\"\"\"\n        Return a level of the header if the given line is indeed a header.\n\n        Level of the header is determined by the number of # symbols.\n        \"\"\"\n        header_symbols = re.match(md_const.HEADER_REGEX, line)\n        # Header is valid only if it line starts with header\n        if header_symbols is not None and header_symbols.regs[0][0] == 0:\n            return header_symbols.regs[0][1]\n        return None\n\n    def _does_start_with(self, line: str, start_chars: str) -> bool:\n\"\"\"Determine whether the line starts with given characters.\"\"\"\n        return line.startswith(start_chars)\n\n    def _does_contain(self, line: str, reg: str) -> bool:\n\"\"\"Determine if the line matches regex.\"\"\"\n        if len(line) == 0 and reg != r'':\n            return False\n        regexp = re.compile(reg)\n        return regexp.search(line) is not None\n\n    def _read_code_lines(self, lines: List[str], line: str, i: int) -> tuple[list[str], int]:\n\"\"\"Read code block.\"\"\"\n        code_lines = [line]\n        while True:\n            if i >= len(lines):\n                raise TrestleError(f'Code block is not closed: {code_lines}')\n\n            line = lines[i]\n            code_lines.append(line)\n            i += 1\n            if self._does_contain(line, md_const.CODEBLOCK_DEF):\n                break\n        return code_lines, i\n\n    def _read_html_block(self, lines: List[str], line: str, i: int, ending_regex: str) -> tuple[list[str], int]:\n\"\"\"Read html block.\"\"\"\n        html_block = [line]\n        if self._does_contain(line, r'<br[ /]*>'):\n            return html_block, i\n        if self._does_contain(line, ending_regex):\n            return html_block, i\n        while True:\n            if i >= len(lines):\n                raise TrestleError(f'HTML block is not closed: {html_block}')\n\n            line = lines[i]\n            html_block.append(line)\n            i += 1\n            if self._does_contain(line, ending_regex):\n                break\n        return html_block, i\n\n    def _read_table_block(self, lines: List[str], line: str, i: int) -> tuple[list[str], int]:\n\"\"\"Read table.\"\"\"\n        table_block = [line]\n        while True:\n            if i >= len(lines):\n                return table_block, i\n\n            line = lines[i]\n            if not self._does_contain(line, md_const.TABLE_REGEX):\n                table_block.append(line)\n                break\n            table_block.append(line)\n            i += 1\n        return table_block, i\n\n    def _rec_traverse(self, node: BaseMarkdownNode, key: str, strict_matching: bool) -> Optional[BaseMarkdownNode]:\n\"\"\"\n        Recursevely traverses the tree and searches for the given key.\n\n        If strict matching is turned off, node will be matched if key is a substring of the node's header.\n        \"\"\"\n        if key.lower() == node.key.lower() or (not strict_matching and key.lower() in node.key.lower()):\n            return node\n        if (not strict_matching and any(key.lower() in el.lower()\n                                        for el in node.content.subnodes_keys)) or (key.lower() in [\n                                            el.lower() for el in node.content.subnodes_keys\n                                        ]):\n            for subnode in node.subnodes:\n                matched_node = self._rec_traverse(subnode, key, strict_matching)\n                if matched_node is not None:\n                    return matched_node\n\n        return None\n\n    def _rec_traverse_all(\n        self, node: BaseMarkdownNode, keys: List[str], strict_matching: bool, stop_recurse_on_first_match: bool\n    ) -> List[BaseMarkdownNode]:\n\"\"\"\n        Recursevely traverse the tree and find all nodes matching the keys.\n\n        If strict matching is turned off, nodes will be matched if key is a substring of the node's header.\n        stop_recurse_on_first_match will return only the highest level key match and not any subnodes\n        \"\"\"\n        found_nodes: List[BaseMarkdownNode] = []\n        for key in keys:\n            if key == node.key or (not strict_matching and key in node.key):\n                found_nodes.append(node)\n                if stop_recurse_on_first_match:\n                    return found_nodes\n        for subnode in node.subnodes:\n            matched_nodes = self._rec_traverse_all(subnode, keys, strict_matching, stop_recurse_on_first_match)\n            found_nodes.extend(matched_nodes)\n        return found_nodes\n\n    def _rec_traverse_header_update(self, node: BaseMarkdownNode, header_map: Dict[str, str]) -> None:\n\"\"\"Recursively traverse tree and update the contents.\"\"\"\n        if node:\n            if node.key != 'root':\n                new_key = header_map[node.key]\n                node.key = new_key\n\n            # update text\n            lines = node.content.raw_text.split('\\n')\n            if lines:\n                for i in range(0, len(lines)):\n                    line = lines[i]\n                    if line in header_map.keys():\n                        new_key = header_map[line]\n                        lines[i] = new_key\n                    elif line.strip(' ') in header_map.keys():\n                        # keep spaces if any\n                        new_key = header_map[line.strip(' ')]\n                        lines[i] = line.replace(line.strip(' '), new_key)\n\n                node.content.raw_text = '\\n'.join(lines)\n\n            # update subnodes\n            if node.content.subnodes_keys:\n                for i in range(0, len(node.content.subnodes_keys)):\n                    subnode_key = node.content.subnodes_keys[i]\n                    if subnode_key in header_map.keys():\n                        new_key = header_map[subnode_key]\n                        node.content.subnodes_keys[i] = new_key\n\n        for subnode in node.subnodes:\n            self._rec_traverse_header_update(subnode, header_map)\n\n    def _get_max_header_lvl(self, lines: List[str]) -> int:\n\"\"\"Go through all lines to determine highest header level. Less # means higher.\"\"\"\n        min_lvl = math.inf\n        for line in lines:\n            line = line.strip(' ')\n            header_lvl = self._get_header_level_if_valid(line)\n\n            if header_lvl is not None and header_lvl < min_lvl:\n                min_lvl = header_lvl\n\n        return min_lvl - 1\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.__init__","title":"__init__(self, key, content, starting_line) special","text":"

                                    Initialize markdown node.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def __init__(self, key: str, content: BaseSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n    self.subnodes: List[BaseMarkdownNode] = []\n    self.key = key\n    self.content = content\n    self.starting_line = starting_line\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.build_tree_from_markdown","title":"build_tree_from_markdown(lines) classmethod","text":"

                                    Construct a tree out of the given markdown.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    @classmethod\ndef build_tree_from_markdown(cls, lines: List[str]) -> BaseMarkdownNode:\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n    ob = cls.__new__(cls)\n    start_level = ob._get_max_header_lvl(lines)\n    ob, _ = ob._build_tree(lines, 'root', 0, start_level)\n    return ob\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.change_header_level_by","title":"change_header_level_by(self, delta_level)","text":"

                                    Change all headers in the tree by specified level up or down.

                                    All children nodes will be modified by specified level as well.

                                    Parameters:

                                    Name Type Description Default delta_level int

                                    each header will be modified by this number, can be negative.

                                    required Source code in trestle/core/markdown/base_markdown_node.py
                                    def change_header_level_by(self, delta_level: int) -> None:\n\"\"\"\n    Change all headers in the tree by specified level up or down.\n\n    All children nodes will be modified by specified level as well.\n\n    Args:\n        delta_level: each header will be modified by this number, can be negative.\n    \"\"\"\n    # construct a map\n    header_map = {}\n    if self.key != 'root':\n        new_key = self._modify_header_level(self.key, delta_level)\n        header_map[self.key] = new_key\n    for key in self.content.subnodes_keys:\n        new_key = self._modify_header_level(key, delta_level)\n        header_map[key] = new_key\n\n    # go through all contents and modify headers\n    self._rec_traverse_header_update(self, header_map)\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.delete_nodes_text","title":"delete_nodes_text(self, keys, strict_matching=True)","text":"

                                    Remove text from this node that is found in matching subnodes.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def delete_nodes_text(self, keys: List[str], strict_matching: bool = True) -> List[str]:\n\"\"\"Remove text from this node that is found in matching subnodes.\"\"\"\n    text_lines = self.content.raw_text.split('\\n')\n    matching_nodes = self.get_all_nodes_for_keys(keys, strict_matching, True)\n    # need to delete from end and proceed backwards\n    sorted_nodes = sorted(matching_nodes, key=lambda node: node.starting_line, reverse=True)\n    for node in sorted_nodes:\n        last_line = node.starting_line + len(node.content.raw_text.split('\\n'))\n        delete_list_from_list(text_lines, list(range(node.starting_line, last_line)))\n    return text_lines\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_all_headers_for_key","title":"get_all_headers_for_key(self, key, strict_matching=True)","text":"

                                    Return all headers contained in the node with a given key.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def get_all_headers_for_key(self, key: str, strict_matching: bool = True) -> Iterable[str]:\n\"\"\"Return all headers contained in the node with a given key.\"\"\"\n    if strict_matching:\n        return list(filter(lambda header: key == header, self.content.subnodes_keys)).__iter__()\n    else:\n        return list(filter(lambda header: key in header, self.content.subnodes_keys)).__iter__()\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_all_headers_for_level","title":"get_all_headers_for_level(self, level)","text":"

                                    Return all headers per specified level of hierarchy.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def get_all_headers_for_level(self, level: int) -> Iterable[str]:\n\"\"\"Return all headers per specified level of hierarchy.\"\"\"\n    return list(\n        filter(lambda header: self._get_header_level_if_valid(header) == level, self.content.subnodes_keys)\n    ).__iter__()\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_all_nodes_for_keys","title":"get_all_nodes_for_keys(self, keys, strict_matching=True, stop_recurse_on_first_match=False)","text":"

                                    Return all nodes for the given keys, substring matching is supported.

                                    Parameters:

                                    Name Type Description Default keys List[str]

                                    List of strings for the headers being collected

                                    required strict_matching bool

                                    Force exact match of key with header vs. simple substring match

                                    True stop_recurse_on_first_match bool

                                    Return first match of any of the keys and don't search subnodes

                                    False

                                    Returns: List of found markdown nodes

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def get_all_nodes_for_keys(\n    self,\n    keys: List[str],\n    strict_matching: bool = True,\n    stop_recurse_on_first_match: bool = False\n) -> List[BaseMarkdownNode]:\n\"\"\"\n    Return all nodes for the given keys, substring matching is supported.\n\n    Args:\n        keys: List of strings for the headers being collected\n        strict_matching: Force exact match of key with header vs. simple substring match\n        stop_recurse_on_first_match: Return first match of any of the keys and don't search subnodes\n\n    Returns: List of found markdown nodes\n    \"\"\"\n    if not strict_matching:\n        if not any(key in el for el in self.content.subnodes_keys for key in keys):\n            return []\n    elif not set(keys).intersection(self.content.subnodes_keys):\n        return []\n\n    return self._rec_traverse_all(self, keys, strict_matching, stop_recurse_on_first_match)\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_node_for_key","title":"get_node_for_key(self, key, strict_matching=True)","text":"

                                    Return a first node for the given key, substring matching is supported. The method is case insensitive.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def get_node_for_key(self, key: str, strict_matching: bool = True) -> Optional[BaseMarkdownNode]:\n\"\"\"Return a first node for the given key, substring matching is supported. The method is case insensitive.\"\"\"\n    if not strict_matching:\n        if not any(key.lower() in el.lower() for el in self.content.subnodes_keys):\n            return None\n        elif len(as_filtered_list(self.content.subnodes_keys, lambda el: key.lower() in el.lower())) > 1:\n            logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n    else:\n        if key.lower() not in [el.lower() for el in self.content.subnodes_keys]:\n            return None\n        elif len(as_filtered_list(self.content.subnodes_keys, lambda el: el.lower() == key.lower())) > 1:\n            logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n\n    return self._rec_traverse(self, key, strict_matching)\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_node_header_lvl","title":"get_node_header_lvl(self)","text":"

                                    Return current node header level.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def get_node_header_lvl(self) -> Optional[int]:\n\"\"\"Return current node header level.\"\"\"\n    return self._get_header_level_if_valid(self.key)\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent","title":" BaseSectionContent ","text":"

                                    A content of the node.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    class BaseSectionContent:\n\"\"\"A content of the node.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize section content.\"\"\"\n        self.raw_text = ''\n        self.subnodes_keys: List[str] = []\n\n    def union(self, node: BaseMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n        self.subnodes_keys.append(node.key)\n        self.subnodes_keys.extend(node.content.subnodes_keys)\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent.__init__","title":"__init__(self) special","text":"

                                    Initialize section content.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def __init__(self) -> None:\n\"\"\"Initialize section content.\"\"\"\n    self.raw_text = ''\n    self.subnodes_keys: List[str] = []\n
                                    "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent.union","title":"union(self, node)","text":"

                                    Unites contents together.

                                    Source code in trestle/core/markdown/base_markdown_node.py
                                    def union(self, node: BaseMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n    self.subnodes_keys.append(node.key)\n    self.subnodes_keys.extend(node.content.subnodes_keys)\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/","title":"control_markdown_node","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node","title":"trestle.core.markdown.control_markdown_node","text":"

                                    A control markdown node.

                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.tree_context","title":"tree_context","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode","title":" ControlMarkdownNode (BaseMarkdownNode) ","text":"

                                    Markdown will be read to the tree.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    class ControlMarkdownNode(BaseMarkdownNode):\n\"\"\"Markdown will be read to the tree.\"\"\"\n\n    def __init__(self, key: str, content: ControlSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n        super(ControlMarkdownNode, self).__init__(key, content, starting_line)\n        self.content: ControlSectionContent = content\n\n    def _build_tree(self,\n                    lines: List[str],\n                    root_key: str,\n                    starting_line: int,\n                    level: int,\n                    parent_part_id: str = '') -> Tuple[ControlMarkdownNode, int]:\n\"\"\"\n        Build a tree from the markdown recursively.\n\n        The tree is contructed with valid headers as node's keys\n        and node's content contains everything that is under that header.\n        The subsections are placed into node's children with the same structure.\n\n        A header is valid iff the line starts with # and it is not:\n          1. Inside of the html blocks\n          2. Inside single lined in the <> tags\n          3. Inside the html comment\n          4. Inside any table, code block or blockquotes\n\n        Specific Control Rules:\n          1. If we are in control statement or objective, no subsections are allowed.\n        \"\"\"\n        content = ControlSectionContent()\n        node_children = []\n        i = starting_line\n\n        section_heading_type = self._get_section_heading_type(root_key)\n\n        part_id, part_name, part_title, by_id_part = self._get_part_info_from_section_name(root_key, parent_part_id,\n                                                                                           section_heading_type)\n\n        current_key_lvl = self._get_header_level_if_valid(root_key)\n\n        if section_heading_type == ControlSectionType.UNDEFINED and tree_context.control_id:\n            logger.warning(\n                f'Undefined section {root_key} is found in the markdown for control {tree_context.control_id}. '\n                f'This section will be ignored. Please make sure the spelling is correct.'\n            )\n\n        if current_key_lvl and current_key_lvl == 1 and section_heading_type != ControlSectionType.EDITABLE_CONTENT:\n            # Parse control title\n            if tree_context.control_id:\n                logger.debug(\n                    f'Duplicate control_id is found for the markdown {root_key}, '\n                    f'make sure you have reset tree context before reading another markdown.'\n                    f'Use markdown processor to avoid this error.'\n                )\n                raise TrestleError(\n                    f'Multiple top-level headers are found but only one header is allowed. See line {root_key} '\n                    f'for control {tree_context.control_id}.'\n                )\n            tree_context.control_id, tree_context.control_group, tree_context.control_title = ControlMarkdownNode._parse_control_title_line(root_key)  # noqa: E501\n            content.control_id = tree_context.control_id\n            content.control_group = tree_context.control_group\n            content.control_title = tree_context.control_title\n\n        def _strip_prose_or_none(part: Optional[common.Part]):\n            if part and part.prose:\n                part.prose = part.prose.strip() if part.prose.strip() else None\n\n        def _add_child_prose_if_need(part: common.Part, text: str, should_add: bool):\n            if should_add:\n                part.prose += text\n\n        while i < len(lines):\n            line = lines[i].strip(' ')\n            header_lvl = self._get_header_level_if_valid(line)\n\n            if header_lvl is not None:\n                if header_lvl >= level + 1:\n                    if section_heading_type in [ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE]:\n                        raise TrestleError(\n                            f'Control Statement or Objective sections cannot contain subsections but found: {line}.'\n                            f'Please delete this subsection and refer to docs on the required format.'\n                        )\n                    # build subtree\n                    subtree, i = self._build_tree(lines, line, i + 1, level + 1, part_id)\n                    node_children.append(subtree)\n                    content.union(subtree)\n                    if content.part and subtree.content.part and section_heading_type not in [\n                            ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE, ControlSectionType.GUIDANCE\n                    ]:\n                        # Control statement, objective and guidance have special treatment\n                        # in those sections any subsections go to the prose rather than subparts.\n                        content.part.parts = as_list(content.part.parts)\n                        content.part.parts.append(subtree.content.part)\n                    # Control parts can have general markdown in the prose, if we are in the control part\n                    # add its contents under the prose of a parent\n                    _add_child_prose_if_need(\n                        content.part,\n                        subtree.content.raw_text,\n                        section_heading_type\n                        in [ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE, ControlSectionType.GUIDANCE]\n                    )\n                    continue\n                else:\n                    i -= 1  # need to revert back one line to properly handle next heading\n                    break  # level of the header is above or equal to the current level, subtree is over\n\n            if section_heading_type not in [ControlSectionType.UNDEFINED, ControlSectionType.EDITABLE_CONTENT]:\n                # Read part\n                content.part = self._create_part_if_needed(content.part, part_name, part_id)\n                content.part.title = part_title\n                read_parts = section_heading_type in [ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE]\n                if by_id_part and section_heading_type == ControlSectionType.EDITABLE_BY_ID_PART:\n                    content.by_id_name = by_id_part\n                i = self._process_part_line(i, line, lines, content.part, read_parts=read_parts)\n                continue\n\n            # Nothing to do, simply increment\n            i += 1\n\n        first_line_to_grab = starting_line - 1 if starting_line else 0\n        content.raw_text = '\\n'.join(lines[first_line_to_grab:i])\n\n        _strip_prose_or_none(content.part)\n\n        md_node = ControlMarkdownNode(key=root_key, content=content, starting_line=first_line_to_grab)\n        md_node.subnodes = node_children\n        return md_node, i\n\n    def get_control_statement(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control statement node.\"\"\"\n        return self.get_node_for_key('## Control Statement')\n\n    def get_control_objective(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control objective node.\"\"\"\n        return self.get_node_for_key(const.CONTROL_OBJECTIVE_HEADER)\n\n    def get_control_guidance(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control guidance node.\"\"\"\n        return self.get_node_for_key('## Control Guidance')\n\n    def get_by_id_parts(self) -> Dict[str, List[common.Part]]:\n\"\"\"Get by id editable parts.\"\"\"\n        part_id_to_parts_map = {}\n        for node_key in as_filtered_list(self.content.subnodes_keys, lambda k: re.match(const.PART_REGEX, k)):\n            # A by id part section\n            part_node = self.get_node_for_key(node_key)\n            if not part_node.content.part:\n                raise TrestleError(f'Error no part was found in section {part_node.key}.')\n            if part_node.content.by_id_name not in part_id_to_parts_map:\n                part_id_to_parts_map[part_node.content.by_id_name] = []\n            for subpart in part_node.subnodes:\n                # We only care about subsections of ## Part section\n                if subpart.content.part:\n                    part_id_to_parts_map[part_node.content.by_id_name].append(subpart.content.part)\n\n        return part_id_to_parts_map\n\n    def get_editable_parts_and_subparts(self) -> Optional[List[common.Part]]:\n\"\"\"Get editable parts and subparts if exist.\"\"\"\n        by_id_parts = self.get_by_id_parts()\n        exclude_parts_id = list(by_id_parts.keys())\n        editable_node = self.get_node_for_key(f'# {const.EDITABLE_CONTENT}')\n        parts = self._get_subparts(editable_node, exclude_parts_id)\n        return parts\n\n    def _get_subparts(self,\n                      control_node: ControlMarkdownNode,\n                      exclude_ids: List[str] = None) -> Optional[List[common.Part]]:\n\"\"\"Get subparts of the control part node if exists.\"\"\"\n        if not control_node:\n            raise TrestleError(\n                'No control node was provided to extract subparts. '\n                'Please make sure your markdown contains # Editable Content section.'\n            )\n        parts = []\n        for editable_part in as_filtered_list(control_node.subnodes, lambda p: p.content.part is not None):\n            if editable_part.content.part.id not in exclude_ids:\n                parts.append(editable_part.content.part)\n        return parts\n\n    def _get_section_heading_type(self, root_key: str) -> ControlSectionType:\n\"\"\"Determine the section type based on the heading.\"\"\"\n        if root_key.lower() == '## control statement':\n            return ControlSectionType.STATEMENT\n        elif root_key.lower() == '## control objective':\n            return ControlSectionType.OBJECTIVE\n        elif root_key.lower() == '## control guidance':\n            return ControlSectionType.GUIDANCE\n        elif self._does_contain(root_key, const.PART_REGEX):\n            return ControlSectionType.EDITABLE_BY_ID_PART\n        elif f'# {const.EDITABLE_CONTENT}'.lower() in root_key.lower():\n            return ControlSectionType.EDITABLE_CONTENT\n        elif self._does_contain(root_key, const.CONTROL_REGEX):\n            return ControlSectionType.GENERIC_CONTROL_PART\n        elif '### ' in root_key.lower():\n            return ControlSectionType.GENERIC_SUBPART\n\n        return ControlSectionType.UNDEFINED\n\n    def _get_part_info_from_section_name(self, root_key: str, parent_id: str,\n                                         section_heading_type: ControlSectionType) -> Tuple[str, str, str, str]:\n\"\"\"Get part information such as id, name and title based on the section heading.\"\"\"\n        part_id = ''\n        part_name = ''\n        part_title = None\n        by_part_id = None  # special case used for ## Part\n\n        if section_heading_type in [ControlSectionType.GUIDANCE, ControlSectionType.GENERIC_CONTROL_PART]:\n            prefix = const.CONTROL_HEADER + ' '\n            control_md_heading_label = root_key[len(prefix):].strip()\n            control_md_heading_label_ncname = ControlInterface.strip_to_make_ncname(control_md_heading_label)\n            control_md_heading_label_snakename = spaces_and_caps_to_snake(control_md_heading_label)\n\n        if section_heading_type == ControlSectionType.STATEMENT:\n            part_id = ControlInterface.create_statement_id(tree_context.control_id)\n            part_name = const.STATEMENT\n\n        if section_heading_type == ControlSectionType.OBJECTIVE:\n            part_id = f'{tree_context.control_id}_obj'\n            part_name = 'objective'\n\n        if section_heading_type == ControlSectionType.GUIDANCE:\n            # Read control guidance to a part object\n            part_id = ControlInterface.strip_to_make_ncname(tree_context.control_id + '_gdn')\n            part_name = control_md_heading_label_ncname\n\n        if section_heading_type == ControlSectionType.EDITABLE_BY_ID_PART:\n            # Read editable part\n            by_part_label = re.match(const.PART_REGEX, root_key.lower()).groups(0)[0]\n            control_label_map = tree_context.part_label_to_id_map.get(tree_context.control_id, None)\n            if control_label_map is None:\n                raise TrestleError(f'No label map found for control {tree_context.control_id}')\n            by_part_id = control_label_map.get(by_part_label, None)\n            if by_part_id is None:\n                raise TrestleError(f'No part id found for label {by_part_label} in control {tree_context.control_id}')\n\n            part_name = spaces_and_caps_to_snake(root_key.replace('#', '').replace('.', '').strip())\n            part_id = f'{by_part_id}'\n            part_title = root_key.replace('#', '').strip()\n\n        if section_heading_type == ControlSectionType.GENERIC_CONTROL_PART:\n            # Read other control parts to a part objects\n            part_name = control_md_heading_label_snakename\n            if tree_context.section_to_part_name_map:\n                if control_md_heading_label in tree_context.section_to_part_name_map:\n                    part_name = tree_context.section_to_part_name_map[control_md_heading_label]\n\n                part_id = f'{tree_context.control_id}_{part_name}'\n                part_title = control_md_heading_label\n            else:\n                part_id = spaces_and_caps_to_snake(tree_context.control_id + '_' + control_md_heading_label)\n\n        if section_heading_type == ControlSectionType.GENERIC_SUBPART:\n            # Read other control parts to a part objects\n            match = re.match(const.AFTER_HASHES_REGEX, root_key)\n            if not match:\n                raise TrestleError(f'Unexpected editable header {root_key} found in part {part_id}')\n            part_name_raw = match.groups(0)[0]\n            part_name = spaces_and_caps_to_snake(part_name_raw)\n            parent_suffix = parent_id + '.' if parent_id else ''\n            part_id = parent_suffix + part_name\n\n        return part_id, part_name, part_title, by_part_id\n\n    def get_other_control_parts(self) -> List[Optional[ControlMarkdownNode]]:\n\"\"\"Get all other control parts that are not statement, guidance or objective.\"\"\"\n        all_other_nodes = []\n        all_control_sections = self.get_all_headers_for_key(const.CONTROL_HEADER, False)\n        control_statement = self.get_control_statement()\n        control_objective = self.get_control_objective()\n        control_guidance = self.get_control_guidance()\n        control_statement_heading = control_statement.key if control_statement else ''\n        control_objective_heading = control_objective.key if control_objective else ''\n        control_guidance_heading = control_guidance.key if control_guidance else ''\n        for heading_key in all_control_sections:\n            if heading_key not in {control_statement_heading, control_objective_heading, control_guidance_heading}:\n                section_node = self.get_node_for_key(heading_key)\n                all_other_nodes.append(section_node)\n\n        return all_other_nodes\n\n    def _create_part_if_needed(self, content_part: common.Part, part_name: str, part_id: str, prose: str = ''):\n\"\"\"Create a new part if does not exist or return existing part.\"\"\"\n        if not content_part:\n            if not tree_context.control_id:\n                raise TrestleError(\n                    f'Unexpected error, control id, group and title should be before ## Control {part_name}.'\n                    'However, none was found.'\n                )\n\n            content_part = common.Part(name=part_name, id=part_id, prose=prose)\n\n        return content_part\n\n    def _process_part_line(\n        self, line_idx: int, line: str, lines: List[str], part: common.Part, read_parts: bool = True\n    ) -> int:\n\"\"\"\n        Process line for the part.\n\n        If the read_parts is given and the line starts with '-' then\n        the markdown list will be read to the subparts of the given part.\n        \"\"\"\n        if self._does_start_with(line, HTML_COMMENT_START):\n            comment_lines, line_idx = self._read_html_block(lines, line, line_idx + 1, HTML_COMMENT_END_REGEX)\n            if line_idx >= len(lines):\n                return line_idx\n            line = lines[line_idx]\n\n        if self._does_start_with(line, CODEBLOCK_DEF):\n            code_lines, line_idx = self._read_code_lines(lines, line, line_idx + 1)\n            if line_idx >= len(lines):\n                return line_idx\n            line = lines[line_idx]\n            part.prose += '\\n'.join(code_lines)\n\n        if not line or not line.lstrip():\n            # Empty line\n            part.prose += '\\n'\n            line_idx += 1\n            return line_idx\n\n        if line.lstrip()[0] != '-' or not read_parts:\n            # Line of text in prose\n            part.prose += line + '\\n'\n            line_idx += 1\n        else:\n            # A part of inside of statement part\n            if read_parts:\n                end_idx, parts = self._read_parts(0, line_idx, lines, part.id, [])\n                part.parts = none_if_empty(parts)\n                line_idx = end_idx\n            else:\n                logger.warning(\n                    f'{part.name} does not support subparts, ignoring {line} in control {tree_context.control_id}.'\n                )\n                line_idx += 1\n\n        return line_idx\n\n    def _read_parts(self, indent: int, ii: int, lines: List[str], parent_id: str,\n                    parts: List[common.Part]) -> Tuple[int, List[common.Part]]:\n\"\"\"If indentation level goes up or down, create new list or close current one.\"\"\"\n        while True:\n            ii, new_indent, line = ControlMarkdownNode._get_next_indent(ii, lines)\n            if new_indent < 0:\n                # we are done reading control statement\n                return ii, parts\n            if new_indent == indent:\n                # create new item part and add to current list of parts\n                id_text, prose = ControlMarkdownNode._read_part_id_prose(line)\n                # id_text is the part id and needs to be as a label property value\n                # if none is there then create one from previous part, or use default\n                if not id_text:\n                    prev_label = ControlInterface.get_label(parts[-1]) if parts else ''\n                    id_text = ControlMarkdownNode._create_next_label(prev_label, indent)\n                id_ = ControlInterface.strip_to_make_ncname(parent_id.rstrip('.') + '.' + id_text.strip('.'))\n                name = const.OBJECTIVE_PART if id_.find('_obj') > 0 else const.ITEM\n                prop = common.Property(name='label', value=id_text)\n                part = common.Part(name=name, id=id_, prose=prose, props=[prop])\n                if id_ in [p.id for p in parts]:\n                    logger.warning(\n                        f'Duplicate part id {id_} is found in markdown '\n                        f'{tree_context.control_id}. Please correct the part label in line {line}.'\n                    )\n                parts.append(part)\n                ii += 1\n            elif new_indent > indent:\n                # add new list of parts to last part and continue\n                if len(parts) == 0:\n                    raise TrestleError(f'Improper indentation structure: {line}')\n                ii, new_parts = self._read_parts(new_indent, ii, lines, parts[-1].id, [])\n                if new_parts:\n                    parts[-1].parts = new_parts\n            else:\n                # return list of sub-parts\n                return ii, parts\n\n    @staticmethod\n    def _indent(line: str) -> int:\n\"\"\"Measure indent of non-empty line.\"\"\"\n        if not line:\n            raise TrestleError('Empty line queried for indent.')\n        if line[0] not in [' ', '-', '\\t']:\n            return -1\n\n        indent = 0\n        for ii in range(len(line)):\n            if line[ii] == '-':\n                return indent\n            # if line is indented it must start with -\n            if line[ii] == '\\t':\n                # treat tab as two spaces\n                indent += 2\n            elif line[ii] != ' ':\n                break\n            else:\n                indent += 1\n        raise TrestleError(f'List elements must start with -: {line}')\n\n    @staticmethod\n    def _parse_control_title_line(line: str) -> Tuple[str, str, str]:\n\"\"\"Process the title line and extract the control id, group title (in brackets) and control title.\"\"\"\n        if line.count('-') == 0:\n            raise TrestleError(f'Markdown control title format error, missing - after control id: {line}')\n        split_line = line.split()\n        if len(split_line) < 3 or split_line[2] != '-':\n            raise TrestleError(f'Cannot parse control markdown title for control_id group and title: {line}')\n        # first token after the #\n        control_id = split_line[1]\n        group_title_start = line.find('\\[')\n        group_title_end = line.find('\\]')\n        if group_title_start < 0 or group_title_end < 0 or group_title_start > group_title_end:\n            raise TrestleError(f'unable to read group title for control {control_id}')\n        group_title = line[group_title_start + 2:group_title_end].strip()\n        control_title = line[group_title_end + 2:].strip()\n        return control_id, group_title, control_title\n\n    @staticmethod\n    def _read_part_id_prose(line: str) -> Tuple[str, str]:\n\"\"\"Extract the part id letter or number and prose from line.\"\"\"\n        start = line.find('\\\\[')\n        end = line.find('\\\\]')\n        prose = line.strip() if start < 0 else line[end + 2:].strip()\n        id_ = '' if start < 0 or end < 0 else line[start + 2:end]\n        return id_, prose\n\n    @staticmethod\n    def _create_next_label(prev_label: str, indent: int) -> str:\n\"\"\"\n        Create new label at indent level based on previous label if available.\n\n        If previous label is available, make this the next one in the sequence.\n        Otherwise start with a or 1 on alternate levels of indentation.\n        If alphabetic label reaches z, next one is aa.\n        Numeric ranges from 1 to 9, then 10 etc.\n        \"\"\"\n        if not prev_label:\n            # assume indent goes in steps of 2\n            return ['a', '1'][(indent // 2) % 2]\n        label_prefix = ''\n        label_suffix = prev_label\n        is_char = prev_label[-1] in string.ascii_letters\n        # if it isn't ending in letter or digit just append 'a' to end\n        if not is_char and prev_label[-1] not in string.digits:\n            return prev_label + 'a'\n        # break in middle of string if mixed types\n        if len(prev_label) > 1:\n            ii = len(prev_label) - 1\n            while ii >= 0:\n                if prev_label[ii] not in string.ascii_letters + string.digits:\n                    break\n                if (prev_label[ii] in string.ascii_letters) != is_char:\n                    break\n                ii -= 1\n            if ii >= 0:\n                label_prefix = prev_label[:(ii + 1)]\n                label_suffix = prev_label[(ii + 1):]\n\n        return label_prefix + ControlMarkdownNode._bump_label(label_suffix)\n\n    @staticmethod\n    def _bump_label(label: str) -> str:\n\"\"\"\n        Find next label given a string of 1 or more pure letters or digits.\n\n        The input must be either a string of digits or a string of ascii letters - or empty string.\n        \"\"\"\n        if not label:\n            return 'a'\n        if label[0] in string.digits:\n            return str(int(label) + 1)\n        if len(label) == 1 and label[0].lower() < 'z':\n            return chr(ord(label[0]) + 1)\n        # if this happens to be a string of letters, force it lowercase and bump\n        label = label.lower()\n        factor = 1\n        value = 0\n        # delta is needed because a counts as 0 when first value on right, but 1 for all others\n        delta = 0\n        for letter in label[::-1]:\n            value += (ord(letter) - ord('a') + delta) * factor\n            factor *= 26\n            delta = 1\n\n        value += 1\n\n        new_label = ''\n        delta = 0\n        while value > 0:\n            new_label += chr(ord('a') + value % 26 - delta)\n            value = value // 26\n            delta = 1\n        return new_label[::-1]\n\n    @staticmethod\n    def _get_next_indent(ii: int, lines: List[str], skip_empty_lines: bool = True) -> Tuple[int, int, str]:\n\"\"\"Seek to next content line.  ii remains at line read.\"\"\"\n        while 0 <= ii < len(lines):\n            line = lines[ii]\n            if line and not line.isspace():\n                if line[0] == '#':\n                    return ii, -1, line\n                indent = ControlMarkdownNode._indent(line)\n                if indent >= 0:\n                    # extract text after -\n                    start = indent + 1\n                    while start < len(line) and line[start] == ' ':\n                        start += 1\n                    if start >= len(line):\n                        raise TrestleError(f'Invalid line {line}')\n                    return ii, indent, line[start:]\n                return ii, indent, line\n            elif not skip_empty_lines:\n                return ii, -1, line\n            ii += 1\n        return ii, -1, ''\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.__init__","title":"__init__(self, key, content, starting_line) special","text":"Source code in trestle/core/markdown/control_markdown_node.py
                                    def __init__(self, key: str, content: ControlSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n    super(ControlMarkdownNode, self).__init__(key, content, starting_line)\n    self.content: ControlSectionContent = content\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_by_id_parts","title":"get_by_id_parts(self)","text":"

                                    Get by id editable parts.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def get_by_id_parts(self) -> Dict[str, List[common.Part]]:\n\"\"\"Get by id editable parts.\"\"\"\n    part_id_to_parts_map = {}\n    for node_key in as_filtered_list(self.content.subnodes_keys, lambda k: re.match(const.PART_REGEX, k)):\n        # A by id part section\n        part_node = self.get_node_for_key(node_key)\n        if not part_node.content.part:\n            raise TrestleError(f'Error no part was found in section {part_node.key}.')\n        if part_node.content.by_id_name not in part_id_to_parts_map:\n            part_id_to_parts_map[part_node.content.by_id_name] = []\n        for subpart in part_node.subnodes:\n            # We only care about subsections of ## Part section\n            if subpart.content.part:\n                part_id_to_parts_map[part_node.content.by_id_name].append(subpart.content.part)\n\n    return part_id_to_parts_map\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_control_guidance","title":"get_control_guidance(self)","text":"

                                    Get control guidance node.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def get_control_guidance(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control guidance node.\"\"\"\n    return self.get_node_for_key('## Control Guidance')\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_control_objective","title":"get_control_objective(self)","text":"

                                    Get control objective node.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def get_control_objective(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control objective node.\"\"\"\n    return self.get_node_for_key(const.CONTROL_OBJECTIVE_HEADER)\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_control_statement","title":"get_control_statement(self)","text":"

                                    Get control statement node.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def get_control_statement(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control statement node.\"\"\"\n    return self.get_node_for_key('## Control Statement')\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_editable_parts_and_subparts","title":"get_editable_parts_and_subparts(self)","text":"

                                    Get editable parts and subparts if exist.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def get_editable_parts_and_subparts(self) -> Optional[List[common.Part]]:\n\"\"\"Get editable parts and subparts if exist.\"\"\"\n    by_id_parts = self.get_by_id_parts()\n    exclude_parts_id = list(by_id_parts.keys())\n    editable_node = self.get_node_for_key(f'# {const.EDITABLE_CONTENT}')\n    parts = self._get_subparts(editable_node, exclude_parts_id)\n    return parts\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_other_control_parts","title":"get_other_control_parts(self)","text":"

                                    Get all other control parts that are not statement, guidance or objective.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def get_other_control_parts(self) -> List[Optional[ControlMarkdownNode]]:\n\"\"\"Get all other control parts that are not statement, guidance or objective.\"\"\"\n    all_other_nodes = []\n    all_control_sections = self.get_all_headers_for_key(const.CONTROL_HEADER, False)\n    control_statement = self.get_control_statement()\n    control_objective = self.get_control_objective()\n    control_guidance = self.get_control_guidance()\n    control_statement_heading = control_statement.key if control_statement else ''\n    control_objective_heading = control_objective.key if control_objective else ''\n    control_guidance_heading = control_guidance.key if control_guidance else ''\n    for heading_key in all_control_sections:\n        if heading_key not in {control_statement_heading, control_objective_heading, control_guidance_heading}:\n            section_node = self.get_node_for_key(heading_key)\n            all_other_nodes.append(section_node)\n\n    return all_other_nodes\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent","title":" ControlSectionContent (BaseSectionContent) ","text":"

                                    A content of the node.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    class ControlSectionContent(BaseSectionContent):\n\"\"\"A content of the node.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize section content.\n\n        Attributes:\n            part: A part that is found in markdown. A part is defined in markdown by two or more # symbols\n            by_id_name: Required for parts defined as ## Part a in a markdown\n        \"\"\"\n        super(ControlSectionContent, self).__init__()\n        self.part = None\n        self.by_id_name = ''\n\n    def union(self, node: ControlMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n        super().union(node)\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent.__init__","title":"__init__(self) special","text":"

                                    Initialize section content.

                                    Attributes:

                                    Name Type Description part

                                    A part that is found in markdown. A part is defined in markdown by two or more # symbols

                                    by_id_name

                                    Required for parts defined as ## Part a in a markdown

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def __init__(self):\n\"\"\"Initialize section content.\n\n    Attributes:\n        part: A part that is found in markdown. A part is defined in markdown by two or more # symbols\n        by_id_name: Required for parts defined as ## Part a in a markdown\n    \"\"\"\n    super(ControlSectionContent, self).__init__()\n    self.part = None\n    self.by_id_name = ''\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent.union","title":"union(self, node)","text":"

                                    Unites contents together.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def union(self, node: ControlMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n    super().union(node)\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType","title":" ControlSectionType (Enum) ","text":"

                                    A type of the section in the markdown.

                                    Supported types: 1 - Control Statement 2 - Control Objective 3 - Control Guidance 4 - ## Part foo 5 - Control foo 6 - ### foo 7 - # Editable content

                                    Matching is case-insensitive.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    class ControlSectionType(Enum):\n\"\"\"A type of the section in the markdown.\n\n    Supported types:\n    1 - Control Statement\n    2 - Control Objective\n    3 - Control Guidance\n    4 - ## Part foo\n    5 - Control foo\n    6 - ### foo\n    7 - # Editable content\n\n    Matching is case-insensitive.\n    \"\"\"\n\n    STATEMENT = 1\n    OBJECTIVE = 2\n    GUIDANCE = 3\n    EDITABLE_BY_ID_PART = 4\n    GENERIC_CONTROL_PART = 5\n    GENERIC_SUBPART = 6\n    EDITABLE_CONTENT = 7\n    UNDEFINED = 8\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.EDITABLE_BY_ID_PART","title":"EDITABLE_BY_ID_PART","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.EDITABLE_CONTENT","title":"EDITABLE_CONTENT","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.GENERIC_CONTROL_PART","title":"GENERIC_CONTROL_PART","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.GENERIC_SUBPART","title":"GENERIC_SUBPART","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.GUIDANCE","title":"GUIDANCE","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.OBJECTIVE","title":"OBJECTIVE","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.STATEMENT","title":"STATEMENT","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.UNDEFINED","title":"UNDEFINED","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext","title":" TreeContext ","text":"

                                    A shared singleton tree context.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    class TreeContext:\n\"\"\"A shared singleton tree context.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize tree context.\"\"\"\n        self.control_id = ''\n        self.control_group = ''\n        self.control_title = ''\n        self.part_label_to_id_map = None\n        self.section_to_part_name_map = None\n\n    def reset(self):\n\"\"\"Reset global control tree context.\"\"\"\n        self.control_id = ''\n        self.control_group = ''\n        self.control_title = ''\n        self.part_label_to_id_map = None\n        self.section_to_part_name_map = None\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext.__init__","title":"__init__(self) special","text":"

                                    Initialize tree context.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def __init__(self):\n\"\"\"Initialize tree context.\"\"\"\n    self.control_id = ''\n    self.control_group = ''\n    self.control_title = ''\n    self.part_label_to_id_map = None\n    self.section_to_part_name_map = None\n
                                    "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext.reset","title":"reset(self)","text":"

                                    Reset global control tree context.

                                    Source code in trestle/core/markdown/control_markdown_node.py
                                    def reset(self):\n\"\"\"Reset global control tree context.\"\"\"\n    self.control_id = ''\n    self.control_group = ''\n    self.control_title = ''\n    self.part_label_to_id_map = None\n    self.section_to_part_name_map = None\n
                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/","title":"docs_markdown_node","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node","title":"trestle.core.markdown.docs_markdown_node","text":"

                                    A docs markdown node.

                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode","title":" DocsMarkdownNode (BaseMarkdownNode) ","text":"

                                    Markdown will be read to the tree.

                                    Source code in trestle/core/markdown/docs_markdown_node.py
                                    class DocsMarkdownNode(BaseMarkdownNode):\n\"\"\"Markdown will be read to the tree.\"\"\"\n\n    def __init__(self, key: str, content: DocsSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n        super(DocsMarkdownNode, self).__init__(key, content, starting_line)\n        self.content: DocsSectionContent = content\n\n    @classmethod\n    def build_tree_from_markdown(cls, lines: List[str], governed_header: Optional[str] = None):\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n        ob = cls.__new__(cls)\n        start_level = ob._get_max_header_lvl(lines)\n        ob, _ = ob._build_tree(lines, 'root', 0, start_level, governed_header)\n        return ob\n\n    def _build_tree(\n        self,\n        lines: List[str],\n        root_key: str,\n        starting_line: int,\n        level: int,\n        governed_header: Optional[str] = None\n    ) -> Tuple[DocsMarkdownNode, int]:\n\"\"\"\n        Build a tree from the markdown recursively.\n\n        The tree is contructed with valid headers as node's keys\n        and node's content contains everything that is under that header.\n        The subsections are placed into node's children with the same structure.\n\n        A header is valid iff the line starts with # and it is not:\n          1. Inside of the html blocks\n          2. Inside single lined in the <> tags\n          3. Inside the html comment\n          4. Inside any table, code block or blockquotes\n        \"\"\"\n        content = DocsSectionContent()\n        node_children = []\n        i = starting_line\n\n        while True:\n            if i >= len(lines):\n                break\n            line = lines[i].strip(' ')\n            header_lvl = self._get_header_level_if_valid(line)\n\n            if header_lvl is not None:\n                if header_lvl >= level + 1:\n                    # build subtree\n                    subtree, i = self._build_tree(lines, line, i + 1, level + 1, governed_header)\n                    node_children.append(subtree)\n                    content.union(subtree)\n                else:\n                    break  # level of the header is above or equal to the current level, subtree is over\n            elif self._does_start_with(line, md_const.CODEBLOCK_DEF):\n                code_lines, i = self._read_code_lines(lines, line, i + 1)\n                content.code_lines.extend(code_lines)\n            elif self._does_start_with(line, md_const.HTML_COMMENT_START):\n                html_lines, i = self._read_html_block(lines, line, i + 1, md_const.HTML_COMMENT_END_REGEX)\n                content.html_lines.extend(html_lines)\n            elif self._does_contain(line, md_const.HTML_TAG_REGEX_START):\n                html_lines, i = self._read_html_block(lines, line, i + 1, md_const.HTML_TAG_REGEX_END)\n                content.html_lines.extend(html_lines)\n            elif self._does_start_with(line, md_const.TABLE_SYMBOL):\n                table_block, i = self._read_table_block(lines, line, i + 1)\n                content.tables.extend(table_block)\n            elif self._does_start_with(line, md_const.BLOCKQUOTE_CHAR):\n                content.blockquotes.append(line)\n                i += 1\n            elif governed_header is not None and self._does_contain(\n                    root_key, fr'^[#]+ {governed_header}$') and self._does_contain(line, md_const.GOVERNED_DOC_REGEX):\n                regexp = re.compile(md_const.GOVERNED_DOC_REGEX)\n                match = regexp.search(line)\n                header = match.group(0).strip('*').strip(':')\n                content.governed_document.append(header)\n                i += 1\n            else:\n                content.text.append(line)\n                i += 1\n\n        first_line_to_grab = starting_line - 1 if starting_line else 0\n        content.raw_text = '\\n'.join(lines[first_line_to_grab:i])\n        md_node = DocsMarkdownNode(key=root_key, content=content, starting_line=first_line_to_grab)\n        md_node.subnodes = node_children\n        return md_node, i\n
                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode.__init__","title":"__init__(self, key, content, starting_line) special","text":"Source code in trestle/core/markdown/docs_markdown_node.py
                                    def __init__(self, key: str, content: DocsSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n    super(DocsMarkdownNode, self).__init__(key, content, starting_line)\n    self.content: DocsSectionContent = content\n
                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown","title":"build_tree_from_markdown(lines, governed_header=None) classmethod","text":"

                                    Construct a tree out of the given markdown.

                                    Source code in trestle/core/markdown/docs_markdown_node.py
                                    @classmethod\ndef build_tree_from_markdown(cls, lines: List[str], governed_header: Optional[str] = None):\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n    ob = cls.__new__(cls)\n    start_level = ob._get_max_header_lvl(lines)\n    ob, _ = ob._build_tree(lines, 'root', 0, start_level, governed_header)\n    return ob\n
                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent","title":" DocsSectionContent (BaseSectionContent) ","text":"

                                    A content of the node.

                                    Source code in trestle/core/markdown/docs_markdown_node.py
                                    class DocsSectionContent(BaseSectionContent):\n\"\"\"A content of the node.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize section content.\"\"\"\n        super(DocsSectionContent, self).__init__()\n        self.tables = []\n        self.text = []\n        self.code_lines = []\n        self.html_lines = []\n        self.blockquotes = []\n        self.governed_document = []\n\n    def union(self, node: DocsMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n        super().union(node)\n        self.code_lines.extend(node.content.code_lines)\n        self.html_lines.extend(node.content.html_lines)\n        self.tables.extend(node.content.tables)\n        self.blockquotes.extend(node.content.blockquotes)\n
                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent.__init__","title":"__init__(self) special","text":"Source code in trestle/core/markdown/docs_markdown_node.py
                                    def __init__(self):\n\"\"\"Initialize section content.\"\"\"\n    super(DocsSectionContent, self).__init__()\n    self.tables = []\n    self.text = []\n    self.code_lines = []\n    self.html_lines = []\n    self.blockquotes = []\n    self.governed_document = []\n
                                    "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent.union","title":"union(self, node)","text":"

                                    Unites contents together.

                                    Source code in trestle/core/markdown/docs_markdown_node.py
                                    def union(self, node: DocsMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n    super().union(node)\n    self.code_lines.extend(node.content.code_lines)\n    self.html_lines.extend(node.content.html_lines)\n    self.tables.extend(node.content.tables)\n    self.blockquotes.extend(node.content.blockquotes)\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_api/","title":"markdown_api","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api","title":"trestle.core.markdown.markdown_api","text":"

                                    A markdown API.

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI","title":" MarkdownAPI ","text":"

                                    A common API that wraps around the existing markdown functionality.

                                    Source code in trestle/core/markdown/markdown_api.py
                                    class MarkdownAPI:\n\"\"\"A common API that wraps around the existing markdown functionality.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize markdown API.\"\"\"\n        self.processor = MarkdownProcessor()\n        self.validator = None\n\n    def load_validator_with_template(\n        self,\n        md_template_path: pathlib.Path,\n        validate_yaml_header: bool,\n        validate_md_body: bool,\n        governed_section: Optional[str] = None,\n        validate_template: bool = False\n    ) -> None:\n\"\"\"Load and initialize markdown validator.\"\"\"\n        try:\n            self.processor.governed_header = governed_section\n            if validate_template:\n                template_header, template_tree = self.processor.process_markdown(md_template_path, validate_yaml_header,\n                                                                                 validate_md_body or governed_section is\n                                                                                 not None)\n            else:\n                template_header, template_tree = self.processor.process_markdown(md_template_path)\n\n            if not template_header and validate_yaml_header:\n                raise TrestleError(f'Expected yaml header for markdown template where none exists {md_template_path}')\n\n            self.validator = MarkdownValidator(\n                md_template_path,\n                template_header,\n                template_tree,\n                validate_yaml_header,\n                validate_md_body,\n                governed_section\n            )\n        except TrestleError as e:\n            raise TrestleError(f'Error while loading markdown template {md_template_path}: {e}.')\n\n    def validate_instance(self, md_instance_path: pathlib.Path) -> bool:\n\"\"\"Validate a given markdown instance against a template.\"\"\"\n        if self.validator is None:\n            raise TrestleError('Markdown validator is not initialized, load template first.')\n        instance_header, instance_tree = self.processor.process_markdown(md_instance_path)\n        return self.validator.is_valid_against_template(md_instance_path, instance_header, instance_tree)\n\n    def write_markdown_with_header(self, path: pathlib.Path, header: Dict[str, str], md_body: str) -> None:\n\"\"\"Write markdown with the YAML header.\"\"\"\n        try:\n            # use encoding to handle character sets as well as possible\n            with open(path, 'w', encoding=const.FILE_ENCODING, errors='replace') as md_file:\n                md_file.write('---\\n')\n                yaml.safe_dump(header, md_file, sort_keys=False)\n                md_file.write('---\\n\\n')\n                md_file.write(md_body)\n        except IOError as e:\n            raise TrestleError(f'Error while writing markdown file: {e}')\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.__init__","title":"__init__(self) special","text":"

                                    Initialize markdown API.

                                    Source code in trestle/core/markdown/markdown_api.py
                                    def __init__(self) -> None:\n\"\"\"Initialize markdown API.\"\"\"\n    self.processor = MarkdownProcessor()\n    self.validator = None\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.load_validator_with_template","title":"load_validator_with_template(self, md_template_path, validate_yaml_header, validate_md_body, governed_section=None, validate_template=False)","text":"

                                    Load and initialize markdown validator.

                                    Source code in trestle/core/markdown/markdown_api.py
                                    def load_validator_with_template(\n    self,\n    md_template_path: pathlib.Path,\n    validate_yaml_header: bool,\n    validate_md_body: bool,\n    governed_section: Optional[str] = None,\n    validate_template: bool = False\n) -> None:\n\"\"\"Load and initialize markdown validator.\"\"\"\n    try:\n        self.processor.governed_header = governed_section\n        if validate_template:\n            template_header, template_tree = self.processor.process_markdown(md_template_path, validate_yaml_header,\n                                                                             validate_md_body or governed_section is\n                                                                             not None)\n        else:\n            template_header, template_tree = self.processor.process_markdown(md_template_path)\n\n        if not template_header and validate_yaml_header:\n            raise TrestleError(f'Expected yaml header for markdown template where none exists {md_template_path}')\n\n        self.validator = MarkdownValidator(\n            md_template_path,\n            template_header,\n            template_tree,\n            validate_yaml_header,\n            validate_md_body,\n            governed_section\n        )\n    except TrestleError as e:\n        raise TrestleError(f'Error while loading markdown template {md_template_path}: {e}.')\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.validate_instance","title":"validate_instance(self, md_instance_path)","text":"

                                    Validate a given markdown instance against a template.

                                    Source code in trestle/core/markdown/markdown_api.py
                                    def validate_instance(self, md_instance_path: pathlib.Path) -> bool:\n\"\"\"Validate a given markdown instance against a template.\"\"\"\n    if self.validator is None:\n        raise TrestleError('Markdown validator is not initialized, load template first.')\n    instance_header, instance_tree = self.processor.process_markdown(md_instance_path)\n    return self.validator.is_valid_against_template(md_instance_path, instance_header, instance_tree)\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.write_markdown_with_header","title":"write_markdown_with_header(self, path, header, md_body)","text":"

                                    Write markdown with the YAML header.

                                    Source code in trestle/core/markdown/markdown_api.py
                                    def write_markdown_with_header(self, path: pathlib.Path, header: Dict[str, str], md_body: str) -> None:\n\"\"\"Write markdown with the YAML header.\"\"\"\n    try:\n        # use encoding to handle character sets as well as possible\n        with open(path, 'w', encoding=const.FILE_ENCODING, errors='replace') as md_file:\n            md_file.write('---\\n')\n            yaml.safe_dump(header, md_file, sort_keys=False)\n            md_file.write('---\\n\\n')\n            md_file.write(md_body)\n    except IOError as e:\n        raise TrestleError(f'Error while writing markdown file: {e}')\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_const/","title":"markdown_const","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const","title":"trestle.core.markdown.markdown_const","text":"

                                    Markdown specific constants.

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.BLOCKQUOTE_CHAR","title":"BLOCKQUOTE_CHAR","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.CODEBLOCK_DEF","title":"CODEBLOCK_DEF","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.GOVERNED_DOC_REGEX","title":"GOVERNED_DOC_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HEADER_REGEX","title":"HEADER_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_COMMENT_END_REGEX","title":"HTML_COMMENT_END_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_COMMENT_START","title":"HTML_COMMENT_START","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_TAG_REGEX_END","title":"HTML_TAG_REGEX_END","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_TAG_REGEX_START","title":"HTML_TAG_REGEX_START","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.INLINE_CODE_CHAR","title":"INLINE_CODE_CHAR","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.JINJA_DATESTAMP_FORMAT","title":"JINJA_DATESTAMP_FORMAT","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.LIST_CHAR","title":"LIST_CHAR","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.SUBSTITUTION_REGEX","title":"SUBSTITUTION_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.TABLE_REGEX","title":"TABLE_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.TABLE_SYMBOL","title":"TABLE_SYMBOL","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/","title":"markdown_processor","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor","title":"trestle.core.markdown.markdown_processor","text":"

                                    A markdown processor.

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor","title":" MarkdownProcessor ","text":"

                                    A markdown processor.

                                    Source code in trestle/core/markdown/markdown_processor.py
                                    class MarkdownProcessor:\n\"\"\"A markdown processor.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize markdown processor.\"\"\"\n        self.governed_header = None\n\n    def render_gfm_to_html(self, markdown_text: str) -> str:\n\"\"\"Render given Github Flavored Markdown to HTML.\"\"\"\n        try:\n            html = cmarkgfm.github_flavored_markdown_to_html(markdown_text)\n            return html\n        except ValueError as e:\n            raise TrestleError(f'Not a valid Github Flavored markdown: {e}.')\n\n    def process_markdown(self,\n                         md_path: pathlib.Path,\n                         read_header: bool = True,\n                         read_body: bool = True) -> Tuple[Dict, DocsMarkdownNode]:\n\"\"\"Parse the markdown and builds the tree to operate over it.\"\"\"\n        header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header, read_body)\n\n        _ = self.render_gfm_to_html(markdown_wo_header)\n\n        lines = markdown_wo_header.split('\\n')\n        tree = DocsMarkdownNode.build_tree_from_markdown(lines, self.governed_header)\n        return header, tree\n\n    def process_control_markdown(\n        self,\n        md_path: pathlib.Path,\n        cli_section_dict: Dict[str, str] = None,\n        part_label_to_id_map: Dict[str, str] = None\n    ) -> Tuple[Dict, ControlMarkdownNode]:\n\"\"\"Parse control markdown and build tree with identified OSCAL components.\"\"\"\n        try:\n            header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header=True, read_body=True)\n\n            section_to_part_name_map = {}\n            if cli_section_dict is not None:\n                # Read x-trestle-sections to the dictionary and merge it with CLI provided dictionary\n                yaml_header_sections_dict = header.get(const.SECTIONS_TAG, {})\n                merged_dict = merge_dicts(yaml_header_sections_dict, cli_section_dict)\n                section_to_part_name_map = {v: k for k, v in merged_dict.items()}\n            _ = self.render_gfm_to_html(markdown_wo_header)\n\n            lines = markdown_wo_header.split('\\n')\n            tree_context.reset()\n            tree_context.section_to_part_name_map = section_to_part_name_map\n            tree_context.part_label_to_id_map = part_label_to_id_map\n            tree = ControlMarkdownNode.build_tree_from_markdown(lines)\n            tree_context.reset()\n            return header, tree\n        except TrestleError as e:\n            logger.error(f'Error while reading control markdown: {md_path}: {e}')\n            raise e\n\n    def read_markdown_wo_processing(self,\n                                    md_path: pathlib.Path,\n                                    read_header: bool = True,\n                                    read_body: bool = True) -> Tuple[Dict, str]:\n\"\"\"Read markdown header to dictionary and body to string.\"\"\"\n        try:\n            contents = frontmatter.loads(md_path.open('r', encoding=const.FILE_ENCODING).read())\n            header = {}\n            markdown_wo_header = ''\n            if read_header:\n                header = contents.metadata\n            if read_body:\n                markdown_wo_header = contents.content\n\n            return header, markdown_wo_header\n        except UnicodeDecodeError as e:\n            logger.debug(traceback.format_exc())\n            raise TrestleError(f'Markdown cannot be decoded into {const.FILE_ENCODING}, error: {e}')\n        except ScannerError as e:\n            logger.debug(traceback.format_exc())\n            raise TrestleError(f'Header is not in a valid YAML format: {e}')\n        except FileNotFoundError as e:\n            logger.debug(traceback.format_exc())\n            raise TrestleError(f'Markdown with path {md_path}, not found: {e}')\n\n    def fetch_value_from_header(self, md_path: pathlib.Path, key: str) -> Optional[str]:\n\"\"\"Fetch value for the given key from the markdown header if exists.\"\"\"\n        header, _ = self.read_markdown_wo_processing(md_path)\n        value = None\n\n        if key in header.keys():\n            value = header[key]\n\n        return value\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.__init__","title":"__init__(self) special","text":"

                                    Initialize markdown processor.

                                    Source code in trestle/core/markdown/markdown_processor.py
                                    def __init__(self) -> None:\n\"\"\"Initialize markdown processor.\"\"\"\n    self.governed_header = None\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.fetch_value_from_header","title":"fetch_value_from_header(self, md_path, key)","text":"

                                    Fetch value for the given key from the markdown header if exists.

                                    Source code in trestle/core/markdown/markdown_processor.py
                                    def fetch_value_from_header(self, md_path: pathlib.Path, key: str) -> Optional[str]:\n\"\"\"Fetch value for the given key from the markdown header if exists.\"\"\"\n    header, _ = self.read_markdown_wo_processing(md_path)\n    value = None\n\n    if key in header.keys():\n        value = header[key]\n\n    return value\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.process_control_markdown","title":"process_control_markdown(self, md_path, cli_section_dict=None, part_label_to_id_map=None)","text":"

                                    Parse control markdown and build tree with identified OSCAL components.

                                    Source code in trestle/core/markdown/markdown_processor.py
                                    def process_control_markdown(\n    self,\n    md_path: pathlib.Path,\n    cli_section_dict: Dict[str, str] = None,\n    part_label_to_id_map: Dict[str, str] = None\n) -> Tuple[Dict, ControlMarkdownNode]:\n\"\"\"Parse control markdown and build tree with identified OSCAL components.\"\"\"\n    try:\n        header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header=True, read_body=True)\n\n        section_to_part_name_map = {}\n        if cli_section_dict is not None:\n            # Read x-trestle-sections to the dictionary and merge it with CLI provided dictionary\n            yaml_header_sections_dict = header.get(const.SECTIONS_TAG, {})\n            merged_dict = merge_dicts(yaml_header_sections_dict, cli_section_dict)\n            section_to_part_name_map = {v: k for k, v in merged_dict.items()}\n        _ = self.render_gfm_to_html(markdown_wo_header)\n\n        lines = markdown_wo_header.split('\\n')\n        tree_context.reset()\n        tree_context.section_to_part_name_map = section_to_part_name_map\n        tree_context.part_label_to_id_map = part_label_to_id_map\n        tree = ControlMarkdownNode.build_tree_from_markdown(lines)\n        tree_context.reset()\n        return header, tree\n    except TrestleError as e:\n        logger.error(f'Error while reading control markdown: {md_path}: {e}')\n        raise e\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.process_markdown","title":"process_markdown(self, md_path, read_header=True, read_body=True)","text":"

                                    Parse the markdown and builds the tree to operate over it.

                                    Source code in trestle/core/markdown/markdown_processor.py
                                    def process_markdown(self,\n                     md_path: pathlib.Path,\n                     read_header: bool = True,\n                     read_body: bool = True) -> Tuple[Dict, DocsMarkdownNode]:\n\"\"\"Parse the markdown and builds the tree to operate over it.\"\"\"\n    header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header, read_body)\n\n    _ = self.render_gfm_to_html(markdown_wo_header)\n\n    lines = markdown_wo_header.split('\\n')\n    tree = DocsMarkdownNode.build_tree_from_markdown(lines, self.governed_header)\n    return header, tree\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.read_markdown_wo_processing","title":"read_markdown_wo_processing(self, md_path, read_header=True, read_body=True)","text":"

                                    Read markdown header to dictionary and body to string.

                                    Source code in trestle/core/markdown/markdown_processor.py
                                    def read_markdown_wo_processing(self,\n                                md_path: pathlib.Path,\n                                read_header: bool = True,\n                                read_body: bool = True) -> Tuple[Dict, str]:\n\"\"\"Read markdown header to dictionary and body to string.\"\"\"\n    try:\n        contents = frontmatter.loads(md_path.open('r', encoding=const.FILE_ENCODING).read())\n        header = {}\n        markdown_wo_header = ''\n        if read_header:\n            header = contents.metadata\n        if read_body:\n            markdown_wo_header = contents.content\n\n        return header, markdown_wo_header\n    except UnicodeDecodeError as e:\n        logger.debug(traceback.format_exc())\n        raise TrestleError(f'Markdown cannot be decoded into {const.FILE_ENCODING}, error: {e}')\n    except ScannerError as e:\n        logger.debug(traceback.format_exc())\n        raise TrestleError(f'Header is not in a valid YAML format: {e}')\n    except FileNotFoundError as e:\n        logger.debug(traceback.format_exc())\n        raise TrestleError(f'Markdown with path {md_path}, not found: {e}')\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.render_gfm_to_html","title":"render_gfm_to_html(self, markdown_text)","text":"

                                    Render given Github Flavored Markdown to HTML.

                                    Source code in trestle/core/markdown/markdown_processor.py
                                    def render_gfm_to_html(self, markdown_text: str) -> str:\n\"\"\"Render given Github Flavored Markdown to HTML.\"\"\"\n    try:\n        html = cmarkgfm.github_flavored_markdown_to_html(markdown_text)\n        return html\n    except ValueError as e:\n        raise TrestleError(f'Not a valid Github Flavored markdown: {e}.')\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_validator/","title":"markdown_validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator","title":"trestle.core.markdown.markdown_validator","text":"

                                    Markdown Validator.

                                    "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator","title":" MarkdownValidator ","text":"

                                    A markdown validator. Validates markdown instance against given template.

                                    Source code in trestle/core/markdown/markdown_validator.py
                                    class MarkdownValidator:\n\"\"\"A markdown validator. Validates markdown instance against given template.\"\"\"\n\n    def __init__(\n        self,\n        tmp_path: pathlib.Path,\n        template_header: Dict,\n        template_tree: DocsMarkdownNode,\n        validate_yaml_header: bool,\n        validate_md_body: bool,\n        governed_section: Optional[str] = None\n    ):\n\"\"\"Initialize markdown validator.\"\"\"\n        self._validate_yaml_header = validate_yaml_header\n        self._validate_md_body = validate_md_body\n        self.governed_section = governed_section.strip(' ') if governed_section is not None else None\n        self.template_header = template_header\n        self.template_tree = template_tree\n        self.template_path = tmp_path\n        self.template_version = self.extract_template_version(self.template_header)\n\n        if self.template_version not in str(self.template_path):\n            raise TrestleError(\n                f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n                + f'Move the template to the folder {self.template_version}'\n            )\n        if 'Version' in self.template_header.keys() and self.template_header['Version'] != self.template_version:\n            raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n        self._ignore_headers = []\n        for key in self.template_header.keys():\n            if key.lower().startswith('x-trestle-'):\n                self._ignore_headers.append(key.lower())\n                if key.lower() == 'x-trestle-ignore':\n                    for key2 in template_header['x-trestle-ignore']:\n                        self._ignore_headers.append(key2.lower())\n\n    def is_valid_against_template(\n        self, instance: pathlib.Path, instance_header: Dict, instance_tree: DocsMarkdownNode\n    ) -> bool:\n\"\"\"\n        Validate instance markdown against template.\n\n        Instance is correct against a template iff:\n            1. For YAML header keys:\n                a. All keys from the template are present and not modified\n                b. Template version in the template and instance match\n            2. On the Markdown w/o YAML header:\n                a. No additional headers of the level 1 were added\n                b. Headers were not reordered\n                c. Headers in the instance should be a superset of the template headers\n                d. Headers must be in heirarchical order (i.e. # then ### then ## is not allowed)\n            3. If Governed Header is given then:\n                a. Governed Header is not modified\n                b. All keys (i.e. key: something) inside the section are present\n\n        Args:\n            instance: a path to the markdown instance that should be validated\n            instance_header: a YAML header extracted from the markdown\n            instance_tree: a tree structure representing markdown contents\n        Returns:\n            Whether or not the the candidate is valid against the template.\n        \"\"\"\n        if self._validate_yaml_header:\n            headers_match = self.compare_keys(self.template_header, instance_header, self._ignore_headers)\n\n            if not headers_match:\n                logger.info(f'YAML header mismatch between template {self.template_path} and instance {instance}')\n                return False\n            elif headers_match and not self._validate_md_body:\n                return True\n\n        if self.governed_section is not None:\n            instance_gov_nodes = instance_tree.get_all_nodes_for_keys([self.governed_section], False)\n            template_gov_nodes = self.template_tree.get_all_nodes_for_keys([self.governed_section], False)\n\n            if not instance_gov_nodes:\n                logger.info(f'Governed section {self.governed_section} not found in instance: {instance}')\n                return False\n\n            if not template_gov_nodes:\n                logger.info(f'Governed section {self.governed_section} not found in template: {self.template_path}')\n                return False\n\n            if [node.key for node in instance_gov_nodes] != [node.key for node in template_gov_nodes]:\n                logger.info(\n                    f'Governed sections were changed, '\n                    f'template expects: {[node.key for node in template_gov_nodes]},'\n                    f'but found {[node.key for node in instance_gov_nodes]}.'\n                )\n                return False\n\n            for instance_gov_node, template_gov_node in zip(instance_gov_nodes, template_gov_nodes):\n                instance_keys = instance_gov_node.content.governed_document\n                template_keys = template_gov_node.content.governed_document\n\n                is_valid = self._validate_headings(instance, template_keys, instance_keys)\n                if not is_valid:\n                    return False\n\n        if self._validate_md_body:\n            instance_keys = instance_tree.content.subnodes_keys\n            template_keys = self.template_tree.content.subnodes_keys\n            if len(template_keys) > len(instance_keys):\n                logger.info(f'Headings in the instance: {instance} were removed.')\n                return False\n\n            instance_lvl1_keys = list(instance_tree.get_all_headers_for_level(1))\n            template_lvl1_keys = list(self.template_tree.get_all_headers_for_level(1))\n            if len(template_lvl1_keys) < len(instance_lvl1_keys):\n                logger.info(f'New headers of level 1 were added to the markdown instance: {instance}. ')\n                return False\n\n            is_valid = self._validate_headings(instance, template_keys, instance_keys)\n            if not is_valid:\n                return False\n\n        return True\n\n    @classmethod\n    def compare_keys(\n        cls,\n        template: Dict[str, Any],\n        candidate: Dict[str, Any],\n        ignore_fields: Optional[Dict[str, Any]] = None\n    ) -> bool:\n\"\"\"\n        Compare a template dictionary against a candidate as to whether key structure is maintained.\n\n        Args:\n            template: Template dict which is used as a model of key-value pairs\n            candidate: Candidate dictionary to be measured\n        Returns:\n            Whether or not the the candidate matches the template keys.\n        \"\"\"\n        if ignore_fields is None:\n            ignore_fields = []\n        for key in list(candidate.keys()):\n            if key.lower() in ignore_fields:\n                candidate.pop(key)\n        for key in list(template.keys()):\n            if key.lower() in ignore_fields:\n                template.pop(key)\n        template_version = cls.extract_template_version(template)\n        candidate_version = cls.extract_template_version(candidate)\n        if template_version != candidate_version:\n            logger.info(f'Versions of the template {template_version} and instance {candidate_version} are different')\n            return False\n\n        if len(template.keys()) != len(candidate.keys()):\n            logger.info(f'Number of keys does not match in template {template} and instance {candidate}')\n            return False\n        for key in template.keys():\n            if key in candidate.keys():\n                if type(template[key]) == dict:\n                    if type(candidate[key]) == dict:\n                        status = cls.compare_keys(template[key], candidate[key], ignore_fields)\n                        if not status:\n                            return status\n                    else:\n                        logger.info(f'Value under {key} must be dictionary in candidate {candidate}')\n                        return False\n            else:\n                logger.info(f'Key {key} is not in candidate {candidate}')\n                return False\n        return True\n\n    def _validate_headings(self, instance: pathlib.Path, template_keys: List[str], instance_keys: List[str]) -> bool:\n\"\"\"Validate instance headings against template.\"\"\"\n        if len(template_keys) > len(instance_keys):\n            logger.info(\n                f'Headings in the instance: {instance} were removed.'\n                f'Expected {len(template_keys)} headings, but found only {len(instance_keys)}.'\n            )\n            return False\n        template_header_pointer = 0\n        present_keys = []\n        for key in instance_keys:\n            if template_header_pointer >= len(template_keys):\n                break\n            if key in template_keys and key not in present_keys:\n                present_keys.append(template_keys[template_keys.index(key)])\n                template_header_pointer += 1\n            elif re.search(md_const.SUBSTITUTION_REGEX, template_keys[template_header_pointer]) is not None:\n                present_keys.append(template_keys[template_header_pointer])\n                template_header_pointer += 1  # skip headers with substitutions\n        diff_keys = set(template_keys) - set(present_keys)\n        if template_header_pointer != len(template_keys) and len(diff_keys) > 0:\n            logger.info(\n                f'Headings in the instance: {instance} were removed. '\n                f'Expected {len(template_keys)} headings, but found only {template_header_pointer}.'\n            )\n            for result in as_list(diff_keys):\n                logger.info(f'Heading {result} in the instance: {instance} was removed or not present ')\n            return False\n        return True\n\n    @classmethod\n    def extract_template_version(cls, header: Dict[str, Any]) -> Optional[str]:\n\"\"\"\n        Extract the template version from the header.\n\n        If no header is found then starting version(0.0.1) will be used by default\n        \"\"\"\n        if TEMPLATE_VERSION_HEADER not in header.keys():\n            return START_TEMPLATE_VERSION\n\n        return header[TEMPLATE_VERSION_HEADER]\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.__init__","title":"__init__(self, tmp_path, template_header, template_tree, validate_yaml_header, validate_md_body, governed_section=None) special","text":"

                                    Initialize markdown validator.

                                    Source code in trestle/core/markdown/markdown_validator.py
                                    def __init__(\n    self,\n    tmp_path: pathlib.Path,\n    template_header: Dict,\n    template_tree: DocsMarkdownNode,\n    validate_yaml_header: bool,\n    validate_md_body: bool,\n    governed_section: Optional[str] = None\n):\n\"\"\"Initialize markdown validator.\"\"\"\n    self._validate_yaml_header = validate_yaml_header\n    self._validate_md_body = validate_md_body\n    self.governed_section = governed_section.strip(' ') if governed_section is not None else None\n    self.template_header = template_header\n    self.template_tree = template_tree\n    self.template_path = tmp_path\n    self.template_version = self.extract_template_version(self.template_header)\n\n    if self.template_version not in str(self.template_path):\n        raise TrestleError(\n            f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n            + f'Move the template to the folder {self.template_version}'\n        )\n    if 'Version' in self.template_header.keys() and self.template_header['Version'] != self.template_version:\n        raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n    self._ignore_headers = []\n    for key in self.template_header.keys():\n        if key.lower().startswith('x-trestle-'):\n            self._ignore_headers.append(key.lower())\n            if key.lower() == 'x-trestle-ignore':\n                for key2 in template_header['x-trestle-ignore']:\n                    self._ignore_headers.append(key2.lower())\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.compare_keys","title":"compare_keys(template, candidate, ignore_fields=None) classmethod","text":"

                                    Compare a template dictionary against a candidate as to whether key structure is maintained.

                                    Parameters:

                                    Name Type Description Default template Dict[str, Any]

                                    Template dict which is used as a model of key-value pairs

                                    required candidate Dict[str, Any]

                                    Candidate dictionary to be measured

                                    required

                                    Returns:

                                    Type Description bool

                                    Whether or not the the candidate matches the template keys.

                                    Source code in trestle/core/markdown/markdown_validator.py
                                    @classmethod\ndef compare_keys(\n    cls,\n    template: Dict[str, Any],\n    candidate: Dict[str, Any],\n    ignore_fields: Optional[Dict[str, Any]] = None\n) -> bool:\n\"\"\"\n    Compare a template dictionary against a candidate as to whether key structure is maintained.\n\n    Args:\n        template: Template dict which is used as a model of key-value pairs\n        candidate: Candidate dictionary to be measured\n    Returns:\n        Whether or not the the candidate matches the template keys.\n    \"\"\"\n    if ignore_fields is None:\n        ignore_fields = []\n    for key in list(candidate.keys()):\n        if key.lower() in ignore_fields:\n            candidate.pop(key)\n    for key in list(template.keys()):\n        if key.lower() in ignore_fields:\n            template.pop(key)\n    template_version = cls.extract_template_version(template)\n    candidate_version = cls.extract_template_version(candidate)\n    if template_version != candidate_version:\n        logger.info(f'Versions of the template {template_version} and instance {candidate_version} are different')\n        return False\n\n    if len(template.keys()) != len(candidate.keys()):\n        logger.info(f'Number of keys does not match in template {template} and instance {candidate}')\n        return False\n    for key in template.keys():\n        if key in candidate.keys():\n            if type(template[key]) == dict:\n                if type(candidate[key]) == dict:\n                    status = cls.compare_keys(template[key], candidate[key], ignore_fields)\n                    if not status:\n                        return status\n                else:\n                    logger.info(f'Value under {key} must be dictionary in candidate {candidate}')\n                    return False\n        else:\n            logger.info(f'Key {key} is not in candidate {candidate}')\n            return False\n    return True\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.extract_template_version","title":"extract_template_version(header) classmethod","text":"

                                    Extract the template version from the header.

                                    If no header is found then starting version(0.0.1) will be used by default

                                    Source code in trestle/core/markdown/markdown_validator.py
                                    @classmethod\ndef extract_template_version(cls, header: Dict[str, Any]) -> Optional[str]:\n\"\"\"\n    Extract the template version from the header.\n\n    If no header is found then starting version(0.0.1) will be used by default\n    \"\"\"\n    if TEMPLATE_VERSION_HEADER not in header.keys():\n        return START_TEMPLATE_VERSION\n\n    return header[TEMPLATE_VERSION_HEADER]\n
                                    "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.is_valid_against_template","title":"is_valid_against_template(self, instance, instance_header, instance_tree)","text":"

                                    Validate instance markdown against template.

                                    Instance is correct against a template iff: 1. For YAML header keys: a. All keys from the template are present and not modified b. Template version in the template and instance match 2. On the Markdown w/o YAML header: a. No additional headers of the level 1 were added b. Headers were not reordered c. Headers in the instance should be a superset of the template headers d. Headers must be in heirarchical order (i.e. # then ### then ## is not allowed) 3. If Governed Header is given then: a. Governed Header is not modified b. All keys (i.e. key: something) inside the section are present

                                    Parameters:

                                    Name Type Description Default instance Path

                                    a path to the markdown instance that should be validated

                                    required instance_header Dict

                                    a YAML header extracted from the markdown

                                    required instance_tree DocsMarkdownNode

                                    a tree structure representing markdown contents

                                    required

                                    Returns:

                                    Type Description bool

                                    Whether or not the the candidate is valid against the template.

                                    Source code in trestle/core/markdown/markdown_validator.py
                                    def is_valid_against_template(\n    self, instance: pathlib.Path, instance_header: Dict, instance_tree: DocsMarkdownNode\n) -> bool:\n\"\"\"\n    Validate instance markdown against template.\n\n    Instance is correct against a template iff:\n        1. For YAML header keys:\n            a. All keys from the template are present and not modified\n            b. Template version in the template and instance match\n        2. On the Markdown w/o YAML header:\n            a. No additional headers of the level 1 were added\n            b. Headers were not reordered\n            c. Headers in the instance should be a superset of the template headers\n            d. Headers must be in heirarchical order (i.e. # then ### then ## is not allowed)\n        3. If Governed Header is given then:\n            a. Governed Header is not modified\n            b. All keys (i.e. key: something) inside the section are present\n\n    Args:\n        instance: a path to the markdown instance that should be validated\n        instance_header: a YAML header extracted from the markdown\n        instance_tree: a tree structure representing markdown contents\n    Returns:\n        Whether or not the the candidate is valid against the template.\n    \"\"\"\n    if self._validate_yaml_header:\n        headers_match = self.compare_keys(self.template_header, instance_header, self._ignore_headers)\n\n        if not headers_match:\n            logger.info(f'YAML header mismatch between template {self.template_path} and instance {instance}')\n            return False\n        elif headers_match and not self._validate_md_body:\n            return True\n\n    if self.governed_section is not None:\n        instance_gov_nodes = instance_tree.get_all_nodes_for_keys([self.governed_section], False)\n        template_gov_nodes = self.template_tree.get_all_nodes_for_keys([self.governed_section], False)\n\n        if not instance_gov_nodes:\n            logger.info(f'Governed section {self.governed_section} not found in instance: {instance}')\n            return False\n\n        if not template_gov_nodes:\n            logger.info(f'Governed section {self.governed_section} not found in template: {self.template_path}')\n            return False\n\n        if [node.key for node in instance_gov_nodes] != [node.key for node in template_gov_nodes]:\n            logger.info(\n                f'Governed sections were changed, '\n                f'template expects: {[node.key for node in template_gov_nodes]},'\n                f'but found {[node.key for node in instance_gov_nodes]}.'\n            )\n            return False\n\n        for instance_gov_node, template_gov_node in zip(instance_gov_nodes, template_gov_nodes):\n            instance_keys = instance_gov_node.content.governed_document\n            template_keys = template_gov_node.content.governed_document\n\n            is_valid = self._validate_headings(instance, template_keys, instance_keys)\n            if not is_valid:\n                return False\n\n    if self._validate_md_body:\n        instance_keys = instance_tree.content.subnodes_keys\n        template_keys = self.template_tree.content.subnodes_keys\n        if len(template_keys) > len(instance_keys):\n            logger.info(f'Headings in the instance: {instance} were removed.')\n            return False\n\n        instance_lvl1_keys = list(instance_tree.get_all_headers_for_level(1))\n        template_lvl1_keys = list(self.template_tree.get_all_headers_for_level(1))\n        if len(template_lvl1_keys) < len(instance_lvl1_keys):\n            logger.info(f'New headers of level 1 were added to the markdown instance: {instance}. ')\n            return False\n\n        is_valid = self._validate_headings(instance, template_keys, instance_keys)\n        if not is_valid:\n            return False\n\n    return True\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/","title":"md_writer","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer","title":"trestle.core.markdown.md_writer","text":"

                                    Create formatted markdown files with optional yaml header.

                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter","title":" MDWriter ","text":"

                                    Simple class to create markdown files.

                                    Source code in trestle/core/markdown/md_writer.py
                                    class MDWriter():\n\"\"\"Simple class to create markdown files.\"\"\"\n\n    def __init__(self, file_path: pathlib.Path, header_comments_dict: Optional[Dict[str, str]] = None):\n\"\"\"Initialize the class.\"\"\"\n        self._file_path = file_path\n        self._lines = []\n        self._indent_level = 0\n        self._indent_size = 2\n        self._yaml_header = None\n        self._header_comments_dict = header_comments_dict\n\n    def _current_indent_space(self):\n        if self._indent_level <= 0:\n            return ''\n        return ' ' * (self._indent_level * self._indent_size)\n\n    def _add_line_raw(self, line: str) -> None:\n        out_line = '' if self._is_blank(line) else line\n        self._lines.append(out_line)\n\n    def _add_indent_level(self, delta: int) -> None:\n        self._indent_level += delta\n\n    def exists(self) -> bool:\n\"\"\"Check if the file already exists.\"\"\"\n        return self._file_path.exists()\n\n    def add_yaml_header(self, header: dict) -> None:\n\"\"\"Add the yaml header.\"\"\"\n        self._yaml_header = header\n\n    def set_indent_level(self, level: int) -> None:\n\"\"\"Set the current indent level.\"\"\"\n        self._indent_level = level\n\n    def set_indent_step_size(self, size: int) -> None:\n\"\"\"Set the indent step size in spaces.\"\"\"\n        self._indent_size = size\n\n    def _is_blank(self, line: str) -> bool:\n        return line.strip() == ''\n\n    def _prev_blank_line(self) -> bool:\n        return len(self._lines) > 0 and self._is_blank(self._lines[-1])\n\n    def new_line(self, line: str) -> None:\n\"\"\"Add a line of text to the output.\"\"\"\n        # prevent double empty lines\n        out_line = '' if self._is_blank(line) else self._current_indent_space() + line\n        if self._prev_blank_line() and out_line == '':\n            return\n        self._add_line_raw(out_line)\n\n    def new_paraline(self, line: str) -> None:\n\"\"\"Add a paragraph and a line to output.\"\"\"\n        self.new_paragraph()\n        self.new_line(line)\n\n    def new_paragraph(self):\n\"\"\"Start a new paragraph.\"\"\"\n        self.new_line('')\n\n    def new_header(self, level: int, title: str, add_new_line_after_header: bool = True) -> None:\n\"\"\"Add new header.\"\"\"\n        # headers might be separated by blank lines\n        self.new_paragraph()\n        self.new_line('#' * level + ' ' + title)\n        if add_new_line_after_header:\n            self.new_paragraph()\n\n    def new_hr(self) -> None:\n\"\"\"Add horizontal rule.\"\"\"\n        self.new_paragraph()\n        self.new_line(const.SSP_MD_HRULE_LINE)\n        self.new_paragraph()\n\n    def new_list(self, list_: List[Any]) -> None:\n\"\"\"Add a list to the markdown.\"\"\"\n        # in general this is a list of lists\n        # if string just write it out\n        if isinstance(list_, str):\n            if self._is_blank(list_):\n                self.new_paragraph()\n            else:\n                self.new_line('- ' + list_)\n        # else it is a sublist so indent\n        else:\n            self._add_indent_level(1)\n            self.new_paragraph()\n            for item in list_:\n                if self._indent_level <= 0:\n                    self.new_paragraph()\n                self.new_list(item)\n            self._add_indent_level(-1)\n\n    def new_table(self, table_list: List[List[str]], header: List[str]):\n\"\"\"Add table to the markdown. All rows must be of equal length.\"\"\"\n        header_str = '| ' + ' | '.join(header) + ' |'\n        sep_str = '|---' * len(header) + '|'\n        self.new_line(header_str)\n        self.new_line(sep_str)\n        for row in table_list:\n            row_str = '| ' + ' | '.join(row) + ' |'\n            self.new_line(row_str)\n\n    def _check_header(self) -> None:\n        while len(self._lines) > 0 and self._lines[0] == '':\n            self._lines = self._lines[1:]\n\n    def write_out(self) -> None:\n\"\"\"Write out the markdown file.\"\"\"\n        self._check_header()\n        try:\n            self._file_path.parent.mkdir(exist_ok=True, parents=True)\n            with open(self._file_path, 'w', encoding=const.FILE_ENCODING) as f:\n                # Make sure yaml header is written first\n                if self._yaml_header:\n                    f.write('---\\n')\n                    yaml = YAML()\n                    yaml.indent(mapping=2, sequence=4, offset=2)\n                    yaml.dump(self._yaml_header, f)\n                    f.write('---\\n\\n')\n\n                f.write('\\n'.join(self._lines))\n                # if last line has text it will need an extra \\n at end\n                if self._lines and self._lines[-1]:\n                    f.write('\\n')\n            # insert helpful comments into the header happens after header is written out\n            for tag, comment in as_dict(self._header_comments_dict).items():\n                if tag in as_dict(self._yaml_header):\n                    file_utils.insert_text_in_file(self._file_path, tag, comment)\n        except IOError as e:\n            logger.debug(f'md_writer error attempting to write out md file {self._file_path} {e}')\n            raise TrestleError(f'Error attempting to write out md file {self._file_path} {e}')\n\n    def get_lines(self) -> List[str]:\n\"\"\"Return the current lines in the file.\"\"\"\n        return self._lines\n\n    def get_text(self) -> str:\n\"\"\"Get the text as currently written.\"\"\"\n        return '\\n'.join(self._lines)\n\n    def cull_headings(self, md_in: pathlib.Path, cull_list: List[str], strict_match: bool = False) -> None:\n\"\"\"\n        Cull headers from the lines of input markdown file with optional strict string match.\n\n        Args:\n            md_in: the path of the markdown file being edited\n            cull_list: the list of strings in headers that are to be culled\n            strict_match: whether to require an exact string match on header key or just a substring\n\n        Returns None and creates new markdown at the path specified during MDWriter construction\n        It is allowed to overwrite the original file\n        \"\"\"\n        markdown_api = MarkdownAPI()\n        header, content = markdown_api.processor.process_markdown(md_in)\n        self._yaml_header = header\n        self._lines = content.delete_nodes_text(cull_list, strict_match)\n        self.write_out()\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.__init__","title":"__init__(self, file_path, header_comments_dict=None) special","text":"

                                    Initialize the class.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def __init__(self, file_path: pathlib.Path, header_comments_dict: Optional[Dict[str, str]] = None):\n\"\"\"Initialize the class.\"\"\"\n    self._file_path = file_path\n    self._lines = []\n    self._indent_level = 0\n    self._indent_size = 2\n    self._yaml_header = None\n    self._header_comments_dict = header_comments_dict\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.add_yaml_header","title":"add_yaml_header(self, header)","text":"

                                    Add the yaml header.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def add_yaml_header(self, header: dict) -> None:\n\"\"\"Add the yaml header.\"\"\"\n    self._yaml_header = header\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.cull_headings","title":"cull_headings(self, md_in, cull_list, strict_match=False)","text":"

                                    Cull headers from the lines of input markdown file with optional strict string match.

                                    Parameters:

                                    Name Type Description Default md_in Path

                                    the path of the markdown file being edited

                                    required cull_list List[str]

                                    the list of strings in headers that are to be culled

                                    required strict_match bool

                                    whether to require an exact string match on header key or just a substring

                                    False

                                    Returns None and creates new markdown at the path specified during MDWriter construction It is allowed to overwrite the original file

                                    Source code in trestle/core/markdown/md_writer.py
                                    def cull_headings(self, md_in: pathlib.Path, cull_list: List[str], strict_match: bool = False) -> None:\n\"\"\"\n    Cull headers from the lines of input markdown file with optional strict string match.\n\n    Args:\n        md_in: the path of the markdown file being edited\n        cull_list: the list of strings in headers that are to be culled\n        strict_match: whether to require an exact string match on header key or just a substring\n\n    Returns None and creates new markdown at the path specified during MDWriter construction\n    It is allowed to overwrite the original file\n    \"\"\"\n    markdown_api = MarkdownAPI()\n    header, content = markdown_api.processor.process_markdown(md_in)\n    self._yaml_header = header\n    self._lines = content.delete_nodes_text(cull_list, strict_match)\n    self.write_out()\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.exists","title":"exists(self)","text":"

                                    Check if the file already exists.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def exists(self) -> bool:\n\"\"\"Check if the file already exists.\"\"\"\n    return self._file_path.exists()\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.get_lines","title":"get_lines(self)","text":"

                                    Return the current lines in the file.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def get_lines(self) -> List[str]:\n\"\"\"Return the current lines in the file.\"\"\"\n    return self._lines\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.get_text","title":"get_text(self)","text":"

                                    Get the text as currently written.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def get_text(self) -> str:\n\"\"\"Get the text as currently written.\"\"\"\n    return '\\n'.join(self._lines)\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_header","title":"new_header(self, level, title, add_new_line_after_header=True)","text":"

                                    Add new header.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def new_header(self, level: int, title: str, add_new_line_after_header: bool = True) -> None:\n\"\"\"Add new header.\"\"\"\n    # headers might be separated by blank lines\n    self.new_paragraph()\n    self.new_line('#' * level + ' ' + title)\n    if add_new_line_after_header:\n        self.new_paragraph()\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_hr","title":"new_hr(self)","text":"

                                    Add horizontal rule.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def new_hr(self) -> None:\n\"\"\"Add horizontal rule.\"\"\"\n    self.new_paragraph()\n    self.new_line(const.SSP_MD_HRULE_LINE)\n    self.new_paragraph()\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_line","title":"new_line(self, line)","text":"

                                    Add a line of text to the output.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def new_line(self, line: str) -> None:\n\"\"\"Add a line of text to the output.\"\"\"\n    # prevent double empty lines\n    out_line = '' if self._is_blank(line) else self._current_indent_space() + line\n    if self._prev_blank_line() and out_line == '':\n        return\n    self._add_line_raw(out_line)\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_list","title":"new_list(self, list_)","text":"

                                    Add a list to the markdown.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def new_list(self, list_: List[Any]) -> None:\n\"\"\"Add a list to the markdown.\"\"\"\n    # in general this is a list of lists\n    # if string just write it out\n    if isinstance(list_, str):\n        if self._is_blank(list_):\n            self.new_paragraph()\n        else:\n            self.new_line('- ' + list_)\n    # else it is a sublist so indent\n    else:\n        self._add_indent_level(1)\n        self.new_paragraph()\n        for item in list_:\n            if self._indent_level <= 0:\n                self.new_paragraph()\n            self.new_list(item)\n        self._add_indent_level(-1)\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_paragraph","title":"new_paragraph(self)","text":"

                                    Start a new paragraph.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def new_paragraph(self):\n\"\"\"Start a new paragraph.\"\"\"\n    self.new_line('')\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_paraline","title":"new_paraline(self, line)","text":"

                                    Add a paragraph and a line to output.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def new_paraline(self, line: str) -> None:\n\"\"\"Add a paragraph and a line to output.\"\"\"\n    self.new_paragraph()\n    self.new_line(line)\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_table","title":"new_table(self, table_list, header)","text":"

                                    Add table to the markdown. All rows must be of equal length.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def new_table(self, table_list: List[List[str]], header: List[str]):\n\"\"\"Add table to the markdown. All rows must be of equal length.\"\"\"\n    header_str = '| ' + ' | '.join(header) + ' |'\n    sep_str = '|---' * len(header) + '|'\n    self.new_line(header_str)\n    self.new_line(sep_str)\n    for row in table_list:\n        row_str = '| ' + ' | '.join(row) + ' |'\n        self.new_line(row_str)\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.set_indent_level","title":"set_indent_level(self, level)","text":"

                                    Set the current indent level.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def set_indent_level(self, level: int) -> None:\n\"\"\"Set the current indent level.\"\"\"\n    self._indent_level = level\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.set_indent_step_size","title":"set_indent_step_size(self, size)","text":"

                                    Set the indent step size in spaces.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def set_indent_step_size(self, size: int) -> None:\n\"\"\"Set the indent step size in spaces.\"\"\"\n    self._indent_size = size\n
                                    "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.write_out","title":"write_out(self)","text":"

                                    Write out the markdown file.

                                    Source code in trestle/core/markdown/md_writer.py
                                    def write_out(self) -> None:\n\"\"\"Write out the markdown file.\"\"\"\n    self._check_header()\n    try:\n        self._file_path.parent.mkdir(exist_ok=True, parents=True)\n        with open(self._file_path, 'w', encoding=const.FILE_ENCODING) as f:\n            # Make sure yaml header is written first\n            if self._yaml_header:\n                f.write('---\\n')\n                yaml = YAML()\n                yaml.indent(mapping=2, sequence=4, offset=2)\n                yaml.dump(self._yaml_header, f)\n                f.write('---\\n\\n')\n\n            f.write('\\n'.join(self._lines))\n            # if last line has text it will need an extra \\n at end\n            if self._lines and self._lines[-1]:\n                f.write('\\n')\n        # insert helpful comments into the header happens after header is written out\n        for tag, comment in as_dict(self._header_comments_dict).items():\n            if tag in as_dict(self._yaml_header):\n                file_utils.insert_text_in_file(self._file_path, tag, comment)\n    except IOError as e:\n        logger.debug(f'md_writer error attempting to write out md file {self._file_path} {e}')\n        raise TrestleError(f'Error attempting to write out md file {self._file_path} {e}')\n
                                    "},{"location":"api_reference/trestle.core.models.actions/","title":"actions","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions","title":"trestle.core.models.actions","text":"

                                    Action wrapper of a command.

                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action","title":" Action (ABC) ","text":"

                                    Action wrapper of a command.

                                    Source code in trestle/core/models/actions.py
                                    class Action(ABC):\n\"\"\"Action wrapper of a command.\"\"\"\n\n    def __init__(self, action_type: ActionType, has_rollback: bool) -> None:\n\"\"\"Initialize an base action.\"\"\"\n        self._type: ActionType = action_type\n        self._has_rollback: bool = has_rollback\n\n        # child class must set this flag once it executes\n        self._has_executed = False\n\n    def to_string(self) -> str:\n\"\"\"Return a string representation.\"\"\"\n        return self.__str__()\n\n    def get_type(self) -> ActionType:\n\"\"\"Return the action type.\"\"\"\n        return self._type\n\n    def _mark_executed(self) -> None:\n\"\"\"Set flag that the action has been executed.\"\"\"\n        self._has_executed = True\n\n    def has_executed(self) -> bool:\n\"\"\"Return if the action has been executed.\"\"\"\n        return self._has_executed\n\n    def _mark_rollback(self) -> None:\n\"\"\"Set flag that the action has been rollbacked.\"\"\"\n        self._has_executed = False\n\n    def has_rollback(self) -> bool:\n\"\"\"Return if rollback of the action is possible.\"\"\"\n        return self._has_rollback\n\n    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two actions are equal.\"\"\"\n        if not isinstance(other, Action):\n            return False\n        if self.get_type() is not other.get_type():\n            return False\n        is_eq = self.__dict__ == other.__dict__\n        return is_eq\n\n    @abstractmethod\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n\n    @abstractmethod\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.__eq__","title":"__eq__(self, other) special","text":"

                                    Check that two actions are equal.

                                    Source code in trestle/core/models/actions.py
                                    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two actions are equal.\"\"\"\n    if not isinstance(other, Action):\n        return False\n    if self.get_type() is not other.get_type():\n        return False\n    is_eq = self.__dict__ == other.__dict__\n    return is_eq\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.__init__","title":"__init__(self, action_type, has_rollback) special","text":"

                                    Initialize an base action.

                                    Source code in trestle/core/models/actions.py
                                    def __init__(self, action_type: ActionType, has_rollback: bool) -> None:\n\"\"\"Initialize an base action.\"\"\"\n    self._type: ActionType = action_type\n    self._has_rollback: bool = has_rollback\n\n    # child class must set this flag once it executes\n    self._has_executed = False\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.execute","title":"execute(self)","text":"

                                    Execute the action.

                                    Source code in trestle/core/models/actions.py
                                    @abstractmethod\ndef execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.get_type","title":"get_type(self)","text":"

                                    Return the action type.

                                    Source code in trestle/core/models/actions.py
                                    def get_type(self) -> ActionType:\n\"\"\"Return the action type.\"\"\"\n    return self._type\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.has_executed","title":"has_executed(self)","text":"

                                    Return if the action has been executed.

                                    Source code in trestle/core/models/actions.py
                                    def has_executed(self) -> bool:\n\"\"\"Return if the action has been executed.\"\"\"\n    return self._has_executed\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.has_rollback","title":"has_rollback(self)","text":"

                                    Return if rollback of the action is possible.

                                    Source code in trestle/core/models/actions.py
                                    def has_rollback(self) -> bool:\n\"\"\"Return if rollback of the action is possible.\"\"\"\n    return self._has_rollback\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.rollback","title":"rollback(self)","text":"

                                    Rollback the action.

                                    Source code in trestle/core/models/actions.py
                                    @abstractmethod\ndef rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.to_string","title":"to_string(self)","text":"

                                    Return a string representation.

                                    Source code in trestle/core/models/actions.py
                                    def to_string(self) -> str:\n\"\"\"Return a string representation.\"\"\"\n    return self.__str__()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType","title":" ActionType (Enum) ","text":"

                                    Action type enum for different action type.

                                    File system related actions have code like 1 Model processing related actions have code like 2

                                    Source code in trestle/core/models/actions.py
                                    class ActionType(Enum):\n\"\"\"Action type enum for different action type.\n\n    File system related actions have code like 1*\n    Model processing related actions have code like 2*\n    \"\"\"\n\n    # create a file or directory path\n    CREATE_PATH = 10\n\n    # remove a file or directory path\n    REMOVE_PATH = 12\n\n    # write element to a destination file or stream\n    WRITE = 11\n\n    # update or add the element at the path\n    UPDATE = 20\n\n    # remove the element at the path\n    REMOVE = 21\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.CREATE_PATH","title":"CREATE_PATH","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.REMOVE","title":"REMOVE","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.REMOVE_PATH","title":"REMOVE_PATH","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.UPDATE","title":"UPDATE","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.WRITE","title":"WRITE","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction","title":" CreatePathAction (Action) ","text":"

                                    Create a file or directory path.

                                    Source code in trestle/core/models/actions.py
                                    class CreatePathAction(Action):\n\"\"\"Create a file or directory path.\"\"\"\n\n    def __init__(self, sub_path: pathlib.Path, clear_content: bool = False) -> None:\n\"\"\"Initialize a create path action.\n\n        It creates all the missing directories in the path.\n        If it is a file, then it also creates an empty file with the name provided\n\n        Arguments:\n            sub_path: this is the desired file or directory path that needs to be created under the project root\n        \"\"\"\n        sub_path = sub_path.resolve()\n\n        self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n        if self._trestle_project_root is None:\n            raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project')\n\n        self._sub_path = sub_path\n        self._created_paths: List[pathlib.Path] = []\n\n        # variables for handling with file content\n        self._clear_content = clear_content\n        self._old_file_content = None\n\n        super().__init__(ActionType.CREATE_PATH, True)\n\n    def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n        return self._trestle_project_root\n\n    def get_created_paths(self) -> List[pathlib.Path]:\n\"\"\"Get the list of paths that were created after being executed.\"\"\"\n        return self._created_paths\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        # find the start of the sub_path relative to trestle project root\n        cur_index = len(self._trestle_project_root.parts)\n\n        # loop through the sub_path parts and create as necessary\n        cur_path = self._trestle_project_root\n        while cur_index < len(self._sub_path.parts):\n            part = self._sub_path.parts[cur_index]\n\n            # create a path relative to the current\n            # it starts with the project root, so we shall always create\n            # sub directories or files relative to the project root\n            cur_path = cur_path / part  # type: ignore\n\n            # create the sub_path file or directory if it does not exists already\n            if cur_path.suffix != '':  # suffix will denote a file\n                if not cur_path.exists():\n                    # create file\n                    cur_path.touch()\n\n                    # add in the list for rollback\n                    self._created_paths.append(cur_path)\n                elif self._clear_content:\n                    # read file content for rollback\n                    with open(cur_path, 'r+', encoding=const.FILE_ENCODING) as fp:\n                        # read all content\n                        self._old_file_content = fp.read()\n\n                        # clear file content\n                        fp.truncate(0)\n            else:\n                if not cur_path.exists():\n                    # create directory\n                    cur_path.mkdir()\n\n                    # add in the list for rollback\n                    self._created_paths.append(cur_path)\n\n            # move to the next part of the sub_path parts\n            cur_index = cur_index + 1\n\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            if len(self._created_paths) > 0:\n                for cur_path in reversed(self._created_paths):\n                    if cur_path.exists():\n                        if cur_path.is_file():\n                            cur_path.unlink()\n                        elif cur_path.is_dir():\n                            cur_path.rmdir()\n\n                self._created_paths.clear()\n\n            # rollback the content of a file if required\n            # we should be here only if there were no path created and the sub_part already existed\n            elif self._sub_path.is_file() and self._sub_path.exists() and self._clear_content is True:\n                if self._old_file_content is not None:\n                    with open(self._sub_path, 'w', encoding=const.FILE_ENCODING) as fp:\n                        fp.write(self._old_file_content)\n\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._sub_path}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.__init__","title":"__init__(self, sub_path, clear_content=False) special","text":"

                                    Initialize a create path action.

                                    It creates all the missing directories in the path. If it is a file, then it also creates an empty file with the name provided

                                    Parameters:

                                    Name Type Description Default sub_path Path

                                    this is the desired file or directory path that needs to be created under the project root

                                    required Source code in trestle/core/models/actions.py
                                    def __init__(self, sub_path: pathlib.Path, clear_content: bool = False) -> None:\n\"\"\"Initialize a create path action.\n\n    It creates all the missing directories in the path.\n    If it is a file, then it also creates an empty file with the name provided\n\n    Arguments:\n        sub_path: this is the desired file or directory path that needs to be created under the project root\n    \"\"\"\n    sub_path = sub_path.resolve()\n\n    self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n    if self._trestle_project_root is None:\n        raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project')\n\n    self._sub_path = sub_path\n    self._created_paths: List[pathlib.Path] = []\n\n    # variables for handling with file content\n    self._clear_content = clear_content\n    self._old_file_content = None\n\n    super().__init__(ActionType.CREATE_PATH, True)\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.__str__","title":"__str__(self) special","text":"

                                    Return string representation.

                                    Source code in trestle/core/models/actions.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._sub_path}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.execute","title":"execute(self)","text":"

                                    Execute the action.

                                    Source code in trestle/core/models/actions.py
                                    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    # find the start of the sub_path relative to trestle project root\n    cur_index = len(self._trestle_project_root.parts)\n\n    # loop through the sub_path parts and create as necessary\n    cur_path = self._trestle_project_root\n    while cur_index < len(self._sub_path.parts):\n        part = self._sub_path.parts[cur_index]\n\n        # create a path relative to the current\n        # it starts with the project root, so we shall always create\n        # sub directories or files relative to the project root\n        cur_path = cur_path / part  # type: ignore\n\n        # create the sub_path file or directory if it does not exists already\n        if cur_path.suffix != '':  # suffix will denote a file\n            if not cur_path.exists():\n                # create file\n                cur_path.touch()\n\n                # add in the list for rollback\n                self._created_paths.append(cur_path)\n            elif self._clear_content:\n                # read file content for rollback\n                with open(cur_path, 'r+', encoding=const.FILE_ENCODING) as fp:\n                    # read all content\n                    self._old_file_content = fp.read()\n\n                    # clear file content\n                    fp.truncate(0)\n        else:\n            if not cur_path.exists():\n                # create directory\n                cur_path.mkdir()\n\n                # add in the list for rollback\n                self._created_paths.append(cur_path)\n\n        # move to the next part of the sub_path parts\n        cur_index = cur_index + 1\n\n    self._mark_executed()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.get_created_paths","title":"get_created_paths(self)","text":"

                                    Get the list of paths that were created after being executed.

                                    Source code in trestle/core/models/actions.py
                                    def get_created_paths(self) -> List[pathlib.Path]:\n\"\"\"Get the list of paths that were created after being executed.\"\"\"\n    return self._created_paths\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.get_trestle_project_root","title":"get_trestle_project_root(self)","text":"

                                    Return the trestle workspace root path.

                                    Source code in trestle/core/models/actions.py
                                    def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n    return self._trestle_project_root\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.rollback","title":"rollback(self)","text":"

                                    Rollback the action.

                                    Source code in trestle/core/models/actions.py
                                    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        if len(self._created_paths) > 0:\n            for cur_path in reversed(self._created_paths):\n                if cur_path.exists():\n                    if cur_path.is_file():\n                        cur_path.unlink()\n                    elif cur_path.is_dir():\n                        cur_path.rmdir()\n\n            self._created_paths.clear()\n\n        # rollback the content of a file if required\n        # we should be here only if there were no path created and the sub_part already existed\n        elif self._sub_path.is_file() and self._sub_path.exists() and self._clear_content is True:\n            if self._old_file_content is not None:\n                with open(self._sub_path, 'w', encoding=const.FILE_ENCODING) as fp:\n                    fp.write(self._old_file_content)\n\n    self._mark_rollback()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction","title":" RemoveAction (Action) ","text":"

                                    Remove sub element at the element path in the source element.

                                    Source code in trestle/core/models/actions.py
                                    class RemoveAction(Action):\n\"\"\"Remove sub element at the element path in the source element.\"\"\"\n\n    def __init__(self, src_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize a remove element action.\"\"\"\n        super().__init__(ActionType.REMOVE, True)\n\n        self._src_element: Element = src_element\n        self._sub_element_path: ElementPath = sub_element_path\n        self._prev_sub_element = None\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        self._prev_sub_element = self._src_element.get_at(self._sub_element_path)\n        self._src_element.set_at(self._sub_element_path, None)\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            self._src_element.set_at(self._sub_element_path, self._prev_sub_element)\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} element at {self._sub_element_path} from {self._src_element}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.__init__","title":"__init__(self, src_element, sub_element_path) special","text":"

                                    Initialize a remove element action.

                                    Source code in trestle/core/models/actions.py
                                    def __init__(self, src_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize a remove element action.\"\"\"\n    super().__init__(ActionType.REMOVE, True)\n\n    self._src_element: Element = src_element\n    self._sub_element_path: ElementPath = sub_element_path\n    self._prev_sub_element = None\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.__str__","title":"__str__(self) special","text":"

                                    Return string representation.

                                    Source code in trestle/core/models/actions.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} element at {self._sub_element_path} from {self._src_element}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.execute","title":"execute(self)","text":"

                                    Execute the action.

                                    Source code in trestle/core/models/actions.py
                                    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    self._prev_sub_element = self._src_element.get_at(self._sub_element_path)\n    self._src_element.set_at(self._sub_element_path, None)\n    self._mark_executed()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.rollback","title":"rollback(self)","text":"

                                    Rollback the action.

                                    Source code in trestle/core/models/actions.py
                                    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        self._src_element.set_at(self._sub_element_path, self._prev_sub_element)\n    self._mark_rollback()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction","title":" RemovePathAction (Action) ","text":"

                                    Remove a file or directory path.

                                    Source code in trestle/core/models/actions.py
                                    class RemovePathAction(Action):\n\"\"\"Remove a file or directory path.\"\"\"\n\n    def __init__(self, sub_path: pathlib.Path) -> None:\n\"\"\"Initialize a remove path action.\n\n        It removes the file or directory recursively into trash.\n\n        Arguments:\n            sub_path: this is the desired file or directory path that needs to be removed under the project root\n        \"\"\"\n        if not isinstance(sub_path, pathlib.Path):\n            raise TrestleError('Sub path must be of type pathlib.Path')\n\n        self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n        if self._trestle_project_root is None:\n            raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project.')\n\n        self._sub_path = sub_path\n\n        super().__init__(ActionType.REMOVE_PATH, True)\n\n    def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n        return self._trestle_project_root\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        if not self._sub_path.exists():\n            logger.debug(f'path {self._sub_path} does not exist in remove path action - ignoring.')\n\n        trash.store(self._sub_path, True)\n\n        # check if parent folder is empty and if so delete\n        parent_dir = pathlib.Path(os.path.dirname(self._sub_path))\n        files = list(parent_dir.iterdir())\n        if not files:\n            trash.store(parent_dir, True)\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            trash_path = trash.to_trash_path(self._sub_path)\n            if trash_path is None or trash_path.exists() is False:\n                # FIXME suppress file contents not found message til trash/rollback behavior is fixed.  # issue 412\n                return\n            trash.recover(self._sub_path, True)\n\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._sub_path}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.__init__","title":"__init__(self, sub_path) special","text":"

                                    Initialize a remove path action.

                                    It removes the file or directory recursively into trash.

                                    Parameters:

                                    Name Type Description Default sub_path Path

                                    this is the desired file or directory path that needs to be removed under the project root

                                    required Source code in trestle/core/models/actions.py
                                    def __init__(self, sub_path: pathlib.Path) -> None:\n\"\"\"Initialize a remove path action.\n\n    It removes the file or directory recursively into trash.\n\n    Arguments:\n        sub_path: this is the desired file or directory path that needs to be removed under the project root\n    \"\"\"\n    if not isinstance(sub_path, pathlib.Path):\n        raise TrestleError('Sub path must be of type pathlib.Path')\n\n    self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n    if self._trestle_project_root is None:\n        raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project.')\n\n    self._sub_path = sub_path\n\n    super().__init__(ActionType.REMOVE_PATH, True)\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.__str__","title":"__str__(self) special","text":"

                                    Return string representation.

                                    Source code in trestle/core/models/actions.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._sub_path}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.execute","title":"execute(self)","text":"

                                    Execute the action.

                                    Source code in trestle/core/models/actions.py
                                    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    if not self._sub_path.exists():\n        logger.debug(f'path {self._sub_path} does not exist in remove path action - ignoring.')\n\n    trash.store(self._sub_path, True)\n\n    # check if parent folder is empty and if so delete\n    parent_dir = pathlib.Path(os.path.dirname(self._sub_path))\n    files = list(parent_dir.iterdir())\n    if not files:\n        trash.store(parent_dir, True)\n    self._mark_executed()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.get_trestle_project_root","title":"get_trestle_project_root(self)","text":"

                                    Return the trestle workspace root path.

                                    Source code in trestle/core/models/actions.py
                                    def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n    return self._trestle_project_root\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.rollback","title":"rollback(self)","text":"

                                    Rollback the action.

                                    Source code in trestle/core/models/actions.py
                                    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        trash_path = trash.to_trash_path(self._sub_path)\n        if trash_path is None or trash_path.exists() is False:\n            # FIXME suppress file contents not found message til trash/rollback behavior is fixed.  # issue 412\n            return\n        trash.recover(self._sub_path, True)\n\n    self._mark_rollback()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction","title":" UpdateAction (Action) ","text":"

                                    Update element at the element path in the destination element with the source element.

                                    Source code in trestle/core/models/actions.py
                                    class UpdateAction(Action):\n\"\"\"Update element at the element path in the destination element with the source element.\"\"\"\n\n    def __init__(self, sub_element, dest_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize an add element action.\n\n        Sub element can be OscalBaseModel, Element, list or None\n        \"\"\"\n        super().__init__(ActionType.UPDATE, True)\n\n        if not Element.is_allowed_sub_element_type(sub_element):\n            allowed_types = Element.get_allowed_sub_element_types()\n            raise TrestleError(\n                f'Sub element \"{sub_element.__class__} is not a allowed sub element types in \"{allowed_types}\"'\n            )\n\n        self._sub_element = sub_element\n        self._dest_element: Element = dest_element\n        self._sub_element_path: ElementPath = sub_element_path\n        self._prev_sub_element = None\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        self._prev_sub_element = self._dest_element.get_at(self._sub_element_path)\n        self._dest_element.set_at(self._sub_element_path, self._sub_element)\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            self._dest_element.set_at(self._sub_element_path, self._prev_sub_element)\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._model_obj.__class__} to {self._dest_element} at {self._sub_element_path}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.__init__","title":"__init__(self, sub_element, dest_element, sub_element_path) special","text":"

                                    Initialize an add element action.

                                    Sub element can be OscalBaseModel, Element, list or None

                                    Source code in trestle/core/models/actions.py
                                    def __init__(self, sub_element, dest_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize an add element action.\n\n    Sub element can be OscalBaseModel, Element, list or None\n    \"\"\"\n    super().__init__(ActionType.UPDATE, True)\n\n    if not Element.is_allowed_sub_element_type(sub_element):\n        allowed_types = Element.get_allowed_sub_element_types()\n        raise TrestleError(\n            f'Sub element \"{sub_element.__class__} is not a allowed sub element types in \"{allowed_types}\"'\n        )\n\n    self._sub_element = sub_element\n    self._dest_element: Element = dest_element\n    self._sub_element_path: ElementPath = sub_element_path\n    self._prev_sub_element = None\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.__str__","title":"__str__(self) special","text":"

                                    Return string representation.

                                    Source code in trestle/core/models/actions.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._model_obj.__class__} to {self._dest_element} at {self._sub_element_path}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.execute","title":"execute(self)","text":"

                                    Execute the action.

                                    Source code in trestle/core/models/actions.py
                                    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    self._prev_sub_element = self._dest_element.get_at(self._sub_element_path)\n    self._dest_element.set_at(self._sub_element_path, self._sub_element)\n    self._mark_executed()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.rollback","title":"rollback(self)","text":"

                                    Rollback the action.

                                    Source code in trestle/core/models/actions.py
                                    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        self._dest_element.set_at(self._sub_element_path, self._prev_sub_element)\n    self._mark_rollback()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction","title":" WriteAction (Action) ","text":"

                                    Write the element to a destination stream.

                                    Source code in trestle/core/models/actions.py
                                    class WriteAction(Action):\n\"\"\"Write the element to a destination stream.\"\"\"\n\n    def __init__(self, writer: Optional[io.TextIOWrapper], element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize an write file action.\"\"\"\n        super().__init__(ActionType.WRITE, True)\n\n        if writer is not None and not issubclass(io.TextIOWrapper, writer.__class__):\n            raise TrestleError(f'Writer must be of io.TextIOWrapper, given f{writer.__class__}')\n\n        self._writer: Optional[io.TextIOWrapper] = writer\n        self._element: Element = element\n        self._content_type: FileContentType = content_type\n        self._lastStreamPos = -1\n        if self._writer is not None:\n            self._lastStreamPos = self._writer.tell()\n\n    def _is_writer_valid(self) -> bool:\n        if self._writer is not None and isinstance(self._writer, io.TextIOWrapper) and not self._writer.closed:\n            return True\n\n        return False\n\n    def _encode(self) -> str:\n\"\"\"Encode the element to appropriate content type.\"\"\"\n        if self._content_type == FileContentType.YAML:\n            return self._element.to_yaml()\n        if self._content_type == FileContentType.JSON:\n            return self._element.to_json()\n\n        raise TrestleError(f'Invalid content type {self._content_type}')\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        if self._element is None:\n            raise TrestleError('Element is empty and cannot write')\n\n        if not self._is_writer_valid():\n            raise TrestleError('Writer is not provided or closed')\n\n        self._writer.write(self._encode())\n        self._writer.flush()\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if not self._is_writer_valid():\n            raise TrestleError('Writer is not provided or closed')\n\n        if self._lastStreamPos < 0:\n            raise TrestleError('Last stream position is not available to rollback to')\n\n        if self.has_executed():\n            self._writer.seek(self._lastStreamPos)\n            self._writer.truncate()\n\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self.get_type()} {self._element}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.__init__","title":"__init__(self, writer, element, content_type) special","text":"

                                    Initialize an write file action.

                                    Source code in trestle/core/models/actions.py
                                    def __init__(self, writer: Optional[io.TextIOWrapper], element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize an write file action.\"\"\"\n    super().__init__(ActionType.WRITE, True)\n\n    if writer is not None and not issubclass(io.TextIOWrapper, writer.__class__):\n        raise TrestleError(f'Writer must be of io.TextIOWrapper, given f{writer.__class__}')\n\n    self._writer: Optional[io.TextIOWrapper] = writer\n    self._element: Element = element\n    self._content_type: FileContentType = content_type\n    self._lastStreamPos = -1\n    if self._writer is not None:\n        self._lastStreamPos = self._writer.tell()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.__str__","title":"__str__(self) special","text":"

                                    Return string representation.

                                    Source code in trestle/core/models/actions.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self.get_type()} {self._element}'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.execute","title":"execute(self)","text":"

                                    Execute the action.

                                    Source code in trestle/core/models/actions.py
                                    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    if self._element is None:\n        raise TrestleError('Element is empty and cannot write')\n\n    if not self._is_writer_valid():\n        raise TrestleError('Writer is not provided or closed')\n\n    self._writer.write(self._encode())\n    self._writer.flush()\n    self._mark_executed()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.rollback","title":"rollback(self)","text":"

                                    Rollback the action.

                                    Source code in trestle/core/models/actions.py
                                    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if not self._is_writer_valid():\n        raise TrestleError('Writer is not provided or closed')\n\n    if self._lastStreamPos < 0:\n        raise TrestleError('Last stream position is not available to rollback to')\n\n    if self.has_executed():\n        self._writer.seek(self._lastStreamPos)\n        self._writer.truncate()\n\n    self._mark_rollback()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction","title":" WriteFileAction (WriteAction) ","text":"

                                    Write the element to a destination file.

                                    Source code in trestle/core/models/actions.py
                                    class WriteFileAction(WriteAction):\n\"\"\"Write the element to a destination file.\"\"\"\n\n    def __init__(self, file_path: pathlib.Path, element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize a write file action.\n\n        It opens the file in append mode. Therefore the file needs to exist even if it is a new file.\n        \"\"\"\n        if not isinstance(file_path, pathlib.Path):\n            raise TrestleError('file_path should be of type pathlib.Path')\n\n        inferred_content_type = FileContentType.to_content_type(file_path.suffix)\n        if inferred_content_type != content_type:\n            raise TrestleError(f'Mismatch between stated content type {content_type.name} and file path {file_path}')\n\n        self._file_path = file_path\n\n        # initialize super without writer for now\n        # Note, execute and rollback sets the writer as appropriate\n        super().__init__(None, element, content_type)\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        if not self._file_path.exists():\n            raise TrestleError(f'File at {self._file_path} does not exist')\n\n        with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n            if self._lastStreamPos < 0:\n                self._lastStreamPos = writer.tell()\n            else:\n                writer.seek(self._lastStreamPos)\n\n            self._writer = writer\n            super().execute()\n\n    def rollback(self) -> None:\n\"\"\"Execute the rollback action.\"\"\"\n        if not self._file_path.exists():\n            raise TrestleError(f'File at {self._file_path} does not exist')\n\n        with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n            self._writer = writer\n            super().rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._element} to \"{self._file_path}\"'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.__init__","title":"__init__(self, file_path, element, content_type) special","text":"

                                    Initialize a write file action.

                                    It opens the file in append mode. Therefore the file needs to exist even if it is a new file.

                                    Source code in trestle/core/models/actions.py
                                    def __init__(self, file_path: pathlib.Path, element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize a write file action.\n\n    It opens the file in append mode. Therefore the file needs to exist even if it is a new file.\n    \"\"\"\n    if not isinstance(file_path, pathlib.Path):\n        raise TrestleError('file_path should be of type pathlib.Path')\n\n    inferred_content_type = FileContentType.to_content_type(file_path.suffix)\n    if inferred_content_type != content_type:\n        raise TrestleError(f'Mismatch between stated content type {content_type.name} and file path {file_path}')\n\n    self._file_path = file_path\n\n    # initialize super without writer for now\n    # Note, execute and rollback sets the writer as appropriate\n    super().__init__(None, element, content_type)\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.__str__","title":"__str__(self) special","text":"Source code in trestle/core/models/actions.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._element} to \"{self._file_path}\"'\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.execute","title":"execute(self)","text":"

                                    Execute the action.

                                    Source code in trestle/core/models/actions.py
                                    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    if not self._file_path.exists():\n        raise TrestleError(f'File at {self._file_path} does not exist')\n\n    with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n        if self._lastStreamPos < 0:\n            self._lastStreamPos = writer.tell()\n        else:\n            writer.seek(self._lastStreamPos)\n\n        self._writer = writer\n        super().execute()\n
                                    "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.rollback","title":"rollback(self)","text":"

                                    Execute the rollback action.

                                    Source code in trestle/core/models/actions.py
                                    def rollback(self) -> None:\n\"\"\"Execute the rollback action.\"\"\"\n    if not self._file_path.exists():\n        raise TrestleError(f'File at {self._file_path} does not exist')\n\n    with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n        self._writer = writer\n        super().rollback()\n
                                    "},{"location":"api_reference/trestle.core.models.elements/","title":"elements","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements","title":"trestle.core.models.elements","text":"

                                    Element wrapper of an OSCAL model element.

                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element","title":" Element ","text":"

                                    Element wrapper of an OSCAL model.

                                    Source code in trestle/core/models/elements.py
                                    class Element:\n\"\"\"Element wrapper of an OSCAL model.\"\"\"\n\n    IGNORE_WRAPPER_ALIAS = '__'\n\n    _allowed_sub_element_types: List[str] = ['Element', 'OscalBaseModel', 'list', 'None', 'dict']\n\n    def __init__(self, elem: OscalBaseModel, wrapper_alias: str = ''):\n\"\"\"Initialize an element wrapper.\n\n        wrapper_alias is the OSCAL alias for the given elem object and used for seriazation in to_json() method.\n\n        For example,\n         - List[Catalog.Group] element should have wrapper alias 'groups'\n         - Catalog element should have wrapper alias 'catalog'\n\n        wrapper_alias is deduced for collection type object\n\n        if wrapper_alias = IGNORE_WRAPPER_ALIAS, then it is ignored and assumed to be json-serializable during to_json()\n        \"\"\"\n        # FIXME: There are instances where elem is a list.\n        self._elem: OscalBaseModel = elem\n\n        if wrapper_alias == '' and wrapper_alias != self.IGNORE_WRAPPER_ALIAS:\n            class_name = elem.__class__.__name__\n            if utils.is_collection_field_type(elem):\n                class_name = self._get_singular_classname()\n                if class_name is None:\n                    raise TrestleError(\n                        f'wrapper_alias not found for a collection type object: {elem.__class__.__name__}'\n                    )\n            wrapper_alias = str_utils.classname_to_alias(class_name, AliasMode.JSON)\n\n        self._wrapper_alias: str = wrapper_alias\n\n    def _get_singular_classname(self) -> str:\n\"\"\"Get the inner class name for list or dict objects.\"\"\"\n        # this assumes all items in list and all values in dict are same type\n        class_name = None\n        root = getattr(self._elem, '__root__', None)\n        if root is not None:\n            type_str = root.__class__.__name__\n            if type_str == 'list':\n                class_name = self._elem.__root__[0].__class__.__name__\n            elif type_str == 'dict':\n                class_name = list(self._elem.__root__.values())[0].__class__.__name__\n        return class_name\n\n    def get(self) -> OscalBaseModel:\n\"\"\"Return the model object.\"\"\"\n        return self._elem\n\n    def _split_element_path(self, element_path: ElementPath):\n\"\"\"Split the element path into root_model and remaing attr names.\"\"\"\n        path_parts = element_path.get()\n        root_model = path_parts[0]\n        path_parts = path_parts[1:]\n\n        return root_model, path_parts\n\n    def get_at(self,\n               element_path: ElementPath = None,\n               check_parent: bool = True) -> Union[OscalBaseModel, List[OscalBaseModel]]:\n\"\"\"Get the element at the specified element path.\n\n        it will return the sub-model object at the path. Sub-model object\n        can be of type OscalBaseModel or List\n        \"\"\"\n        if element_path is None:\n            return self._elem\n\n        # find the root-model and element path parts\n        _, path_parts = self._split_element_path(element_path)\n\n        # TODO validate that self._elem is of same type as root_model\n\n        # initialize the starting element for search\n        elm = self._elem\n        if hasattr(elm, '__root__') and (isinstance(elm.__root__, dict) or isinstance(elm.__root__, list)):\n            elm = elm.__root__\n\n        # if parent exists and does not end with wildcard, use the parent as the starting element for search\n        if check_parent and element_path.get_parent(\n        ) is not None and element_path.get_parent().get_last() != ElementPath.WILDCARD:\n            elm_at = self.get_at(element_path.get_parent())\n            if elm_at is None:\n                raise TrestleNotFoundError(f'Invalid parent path {element_path.get_parent()}')\n            elm = elm_at\n\n        # return the sub-element at the specified path\n        for attr in path_parts:\n            if elm is None:\n                break\n\n            # process for wildcard and array indexes\n\n            if attr == ElementPath.WILDCARD:\n                break\n            elif attr.isnumeric():\n                if isinstance(elm, list):\n                    elm = elm[int(attr)]\n                else:\n                    # index to a non list type should return None\n                    return None\n            else:\n                elm = elm.get_field_value_by_alias(attr)\n\n        return elm\n\n    def get_preceding_element(self, element_path: ElementPath) -> Optional[OscalBaseModel]:\n\"\"\"Get the preceding element in the path.\"\"\"\n        preceding_path = element_path.get_preceding_path()\n        preceding_elm: Optional[OscalBaseModel] = self.get_at(preceding_path)\n        return preceding_elm\n\n    def _get_sub_element_obj(self, sub_element):\n\"\"\"Convert sub element into allowed model obj.\"\"\"\n        if not self.is_allowed_sub_element_type(sub_element):\n            raise TrestleError(\n                f'Sub element must be one of \"{self.get_allowed_sub_element_types()}\", found \"{sub_element.__class__}\"'\n            )\n\n        model_obj = sub_element\n        if isinstance(sub_element, Element):\n            model_obj = sub_element.get()\n\n        return model_obj\n\n    def set_at(self, element_path: ElementPath, sub_element: OscalBaseModel) -> 'Element':\n\"\"\"Set a sub_element at the path in the current element.\n\n        Sub element can be Element, OscalBaseModel, list or None type\n        It returns the element itself so that chaining operation can be done such as\n            `element.set_at(path, sub-element).get()`.\n        \"\"\"\n        # convert the element_path to ElementPath if needed\n        if isinstance(element_path, str):\n            element_path = ElementPath(element_path)\n\n        # convert sub-element to OscalBaseModel if needed\n        model_obj = self._get_sub_element_obj(sub_element)\n\n        # find the root-model and element path parts\n        _, path_parts = self._split_element_path(element_path)\n\n        # TODO validate that self._elem is of same type as root_model\n\n        # If wildcard is present, check the input type and determine the preceding element\n        if element_path.get_last() == ElementPath.WILDCARD:\n            # validate the type is either list or OscalBaseModel\n            if not isinstance(model_obj, list) and not isinstance(model_obj, OscalBaseModel):\n                raise TrestleError(\n                    f'The model object needs to be a List or OscalBaseModel for path with \"{ElementPath.WILDCARD}\"'\n                )\n\n            # since wildcard * is there, we need to go one level up for preceding element in the path\n            preceding_elm = self.get_preceding_element(element_path.get_preceding_path())\n        else:\n            # get the preceding element in the path\n            preceding_elm = self.get_preceding_element(element_path)\n\n        if preceding_elm is None:\n            raise TrestleError(f'Invalid sub element path {element_path} with no valid preceding element')\n\n        # check if it can be a valid sub_element of the parent\n        sub_element_name = element_path.get_element_name().replace('-', '_')\n        if hasattr(preceding_elm, sub_element_name) is False:\n            raise TrestleError(\n                f'Element \"{preceding_elm.__class__}\" does not have the attribute \"{sub_element_name}\" '\n                f'of type \"{model_obj.__class__}\"'\n            )\n\n        # set the sub-element\n        try:\n            setattr(preceding_elm, sub_element_name, model_obj)\n        except ValidationError:\n            sub_element_class = self.get_sub_element_class(preceding_elm, sub_element_name)\n            raise TrestleError(\n                f'Validation error: {sub_element_name} is expected to be \"{sub_element_class}\", '\n                f'but found \"{model_obj.__class__}\"'\n            )\n\n        # returning self will allow to do 'chaining' of commands after set\n        return self\n\n    def to_yaml(self) -> str:\n\"\"\"Convert into YAML string.\"\"\"\n        yaml = YAML(typ='safe')\n        yaml.default_flow_style = False\n        from io import StringIO\n        string_stream = StringIO()\n        yaml.dump(yaml.load(self.to_json(pretty=False)), string_stream)\n        yaml_data = string_stream.getvalue()\n        string_stream.close()\n\n        return yaml_data\n\n    def to_json(self, pretty: bool = True) -> str:\n\"\"\"Convert into JSON string.\"\"\"\n        if self._wrapper_alias == self.IGNORE_WRAPPER_ALIAS:\n            json_data = self._elem.oscal_serialize_json(pretty=pretty, wrapped=False)\n\n        else:\n            # Note before trying to edit this\n            # This transient model allows self._elem not be an OscalBaseModel (e.g. a DICT or LIST)\n            # typing need to be clarified.\n            if isinstance(self._elem, OscalBaseModel):\n                json_data = self._elem.oscal_serialize_json(pretty=pretty)\n            else:\n                dynamic_passer = {}\n                dynamic_passer['TransientField'] = (self._elem.__class__, Field(self, alias=self._wrapper_alias))\n                wrapper_model = create_model('TransientModel', __base__=OscalBaseModel, **dynamic_passer)\n                wrapped_model = wrapper_model.construct(**{self._wrapper_alias: self._elem})\n                json_data = wrapped_model.oscal_serialize_json(pretty=pretty, wrapped=False)\n        return json_data\n\n    @classmethod\n    def get_sub_element_class(cls, parent_elm: OscalBaseModel, sub_element_name: str):\n\"\"\"Get the class of the sub-element.\"\"\"\n        sub_element_class = parent_elm.__fields__[sub_element_name].outer_type_\n        return sub_element_class\n\n    @classmethod\n    def get_allowed_sub_element_types(cls) -> List[str]:\n\"\"\"Get the list of allowed sub element types.\"\"\"\n        return cls._allowed_sub_element_types\n\n    @classmethod\n    def is_allowed_sub_element_type(cls, elm) -> bool:\n\"\"\"Check if is of allowed sub element type.\"\"\"\n        # FIXME: The following logic does not use the _allowed_sub_element_types being defined for the class\n        if (isinstance(elm, Element) or isinstance(elm, OscalBaseModel) or isinstance(elm, list)\n                or isinstance(elm, dict) or elm is None):\n            return True\n\n        return False\n\n    def __str__(self) -> str:\n\"\"\"Return string representation of element.\"\"\"\n        return type(self._elem).__name__\n\n    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two elements are equal.\"\"\"\n        if not isinstance(other, Element):\n            return False\n\n        return self.get() == other.get()\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.IGNORE_WRAPPER_ALIAS","title":"IGNORE_WRAPPER_ALIAS","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.__eq__","title":"__eq__(self, other) special","text":"

                                    Check that two elements are equal.

                                    Source code in trestle/core/models/elements.py
                                    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two elements are equal.\"\"\"\n    if not isinstance(other, Element):\n        return False\n\n    return self.get() == other.get()\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.__init__","title":"__init__(self, elem, wrapper_alias='') special","text":"

                                    Initialize an element wrapper.

                                    wrapper_alias is the OSCAL alias for the given elem object and used for seriazation in to_json() method.

                                    For example, - List[Catalog.Group] element should have wrapper alias 'groups' - Catalog element should have wrapper alias 'catalog'

                                    wrapper_alias is deduced for collection type object

                                    if wrapper_alias = IGNORE_WRAPPER_ALIAS, then it is ignored and assumed to be json-serializable during to_json()

                                    Source code in trestle/core/models/elements.py
                                    def __init__(self, elem: OscalBaseModel, wrapper_alias: str = ''):\n\"\"\"Initialize an element wrapper.\n\n    wrapper_alias is the OSCAL alias for the given elem object and used for seriazation in to_json() method.\n\n    For example,\n     - List[Catalog.Group] element should have wrapper alias 'groups'\n     - Catalog element should have wrapper alias 'catalog'\n\n    wrapper_alias is deduced for collection type object\n\n    if wrapper_alias = IGNORE_WRAPPER_ALIAS, then it is ignored and assumed to be json-serializable during to_json()\n    \"\"\"\n    # FIXME: There are instances where elem is a list.\n    self._elem: OscalBaseModel = elem\n\n    if wrapper_alias == '' and wrapper_alias != self.IGNORE_WRAPPER_ALIAS:\n        class_name = elem.__class__.__name__\n        if utils.is_collection_field_type(elem):\n            class_name = self._get_singular_classname()\n            if class_name is None:\n                raise TrestleError(\n                    f'wrapper_alias not found for a collection type object: {elem.__class__.__name__}'\n                )\n        wrapper_alias = str_utils.classname_to_alias(class_name, AliasMode.JSON)\n\n    self._wrapper_alias: str = wrapper_alias\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.__str__","title":"__str__(self) special","text":"

                                    Return string representation of element.

                                    Source code in trestle/core/models/elements.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation of element.\"\"\"\n    return type(self._elem).__name__\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get","title":"get(self)","text":"

                                    Return the model object.

                                    Source code in trestle/core/models/elements.py
                                    def get(self) -> OscalBaseModel:\n\"\"\"Return the model object.\"\"\"\n    return self._elem\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_allowed_sub_element_types","title":"get_allowed_sub_element_types() classmethod","text":"

                                    Get the list of allowed sub element types.

                                    Source code in trestle/core/models/elements.py
                                    @classmethod\ndef get_allowed_sub_element_types(cls) -> List[str]:\n\"\"\"Get the list of allowed sub element types.\"\"\"\n    return cls._allowed_sub_element_types\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_at","title":"get_at(self, element_path=None, check_parent=True)","text":"

                                    Get the element at the specified element path.

                                    it will return the sub-model object at the path. Sub-model object can be of type OscalBaseModel or List

                                    Source code in trestle/core/models/elements.py
                                    def get_at(self,\n           element_path: ElementPath = None,\n           check_parent: bool = True) -> Union[OscalBaseModel, List[OscalBaseModel]]:\n\"\"\"Get the element at the specified element path.\n\n    it will return the sub-model object at the path. Sub-model object\n    can be of type OscalBaseModel or List\n    \"\"\"\n    if element_path is None:\n        return self._elem\n\n    # find the root-model and element path parts\n    _, path_parts = self._split_element_path(element_path)\n\n    # TODO validate that self._elem is of same type as root_model\n\n    # initialize the starting element for search\n    elm = self._elem\n    if hasattr(elm, '__root__') and (isinstance(elm.__root__, dict) or isinstance(elm.__root__, list)):\n        elm = elm.__root__\n\n    # if parent exists and does not end with wildcard, use the parent as the starting element for search\n    if check_parent and element_path.get_parent(\n    ) is not None and element_path.get_parent().get_last() != ElementPath.WILDCARD:\n        elm_at = self.get_at(element_path.get_parent())\n        if elm_at is None:\n            raise TrestleNotFoundError(f'Invalid parent path {element_path.get_parent()}')\n        elm = elm_at\n\n    # return the sub-element at the specified path\n    for attr in path_parts:\n        if elm is None:\n            break\n\n        # process for wildcard and array indexes\n\n        if attr == ElementPath.WILDCARD:\n            break\n        elif attr.isnumeric():\n            if isinstance(elm, list):\n                elm = elm[int(attr)]\n            else:\n                # index to a non list type should return None\n                return None\n        else:\n            elm = elm.get_field_value_by_alias(attr)\n\n    return elm\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_preceding_element","title":"get_preceding_element(self, element_path)","text":"

                                    Get the preceding element in the path.

                                    Source code in trestle/core/models/elements.py
                                    def get_preceding_element(self, element_path: ElementPath) -> Optional[OscalBaseModel]:\n\"\"\"Get the preceding element in the path.\"\"\"\n    preceding_path = element_path.get_preceding_path()\n    preceding_elm: Optional[OscalBaseModel] = self.get_at(preceding_path)\n    return preceding_elm\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_sub_element_class","title":"get_sub_element_class(parent_elm, sub_element_name) classmethod","text":"

                                    Get the class of the sub-element.

                                    Source code in trestle/core/models/elements.py
                                    @classmethod\ndef get_sub_element_class(cls, parent_elm: OscalBaseModel, sub_element_name: str):\n\"\"\"Get the class of the sub-element.\"\"\"\n    sub_element_class = parent_elm.__fields__[sub_element_name].outer_type_\n    return sub_element_class\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.is_allowed_sub_element_type","title":"is_allowed_sub_element_type(elm) classmethod","text":"

                                    Check if is of allowed sub element type.

                                    Source code in trestle/core/models/elements.py
                                    @classmethod\ndef is_allowed_sub_element_type(cls, elm) -> bool:\n\"\"\"Check if is of allowed sub element type.\"\"\"\n    # FIXME: The following logic does not use the _allowed_sub_element_types being defined for the class\n    if (isinstance(elm, Element) or isinstance(elm, OscalBaseModel) or isinstance(elm, list)\n            or isinstance(elm, dict) or elm is None):\n        return True\n\n    return False\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.set_at","title":"set_at(self, element_path, sub_element)","text":"

                                    Set a sub_element at the path in the current element.

                                    Sub element can be Element, OscalBaseModel, list or None type It returns the element itself so that chaining operation can be done such as element.set_at(path, sub-element).get().

                                    Source code in trestle/core/models/elements.py
                                    def set_at(self, element_path: ElementPath, sub_element: OscalBaseModel) -> 'Element':\n\"\"\"Set a sub_element at the path in the current element.\n\n    Sub element can be Element, OscalBaseModel, list or None type\n    It returns the element itself so that chaining operation can be done such as\n        `element.set_at(path, sub-element).get()`.\n    \"\"\"\n    # convert the element_path to ElementPath if needed\n    if isinstance(element_path, str):\n        element_path = ElementPath(element_path)\n\n    # convert sub-element to OscalBaseModel if needed\n    model_obj = self._get_sub_element_obj(sub_element)\n\n    # find the root-model and element path parts\n    _, path_parts = self._split_element_path(element_path)\n\n    # TODO validate that self._elem is of same type as root_model\n\n    # If wildcard is present, check the input type and determine the preceding element\n    if element_path.get_last() == ElementPath.WILDCARD:\n        # validate the type is either list or OscalBaseModel\n        if not isinstance(model_obj, list) and not isinstance(model_obj, OscalBaseModel):\n            raise TrestleError(\n                f'The model object needs to be a List or OscalBaseModel for path with \"{ElementPath.WILDCARD}\"'\n            )\n\n        # since wildcard * is there, we need to go one level up for preceding element in the path\n        preceding_elm = self.get_preceding_element(element_path.get_preceding_path())\n    else:\n        # get the preceding element in the path\n        preceding_elm = self.get_preceding_element(element_path)\n\n    if preceding_elm is None:\n        raise TrestleError(f'Invalid sub element path {element_path} with no valid preceding element')\n\n    # check if it can be a valid sub_element of the parent\n    sub_element_name = element_path.get_element_name().replace('-', '_')\n    if hasattr(preceding_elm, sub_element_name) is False:\n        raise TrestleError(\n            f'Element \"{preceding_elm.__class__}\" does not have the attribute \"{sub_element_name}\" '\n            f'of type \"{model_obj.__class__}\"'\n        )\n\n    # set the sub-element\n    try:\n        setattr(preceding_elm, sub_element_name, model_obj)\n    except ValidationError:\n        sub_element_class = self.get_sub_element_class(preceding_elm, sub_element_name)\n        raise TrestleError(\n            f'Validation error: {sub_element_name} is expected to be \"{sub_element_class}\", '\n            f'but found \"{model_obj.__class__}\"'\n        )\n\n    # returning self will allow to do 'chaining' of commands after set\n    return self\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.to_json","title":"to_json(self, pretty=True)","text":"

                                    Convert into JSON string.

                                    Source code in trestle/core/models/elements.py
                                    def to_json(self, pretty: bool = True) -> str:\n\"\"\"Convert into JSON string.\"\"\"\n    if self._wrapper_alias == self.IGNORE_WRAPPER_ALIAS:\n        json_data = self._elem.oscal_serialize_json(pretty=pretty, wrapped=False)\n\n    else:\n        # Note before trying to edit this\n        # This transient model allows self._elem not be an OscalBaseModel (e.g. a DICT or LIST)\n        # typing need to be clarified.\n        if isinstance(self._elem, OscalBaseModel):\n            json_data = self._elem.oscal_serialize_json(pretty=pretty)\n        else:\n            dynamic_passer = {}\n            dynamic_passer['TransientField'] = (self._elem.__class__, Field(self, alias=self._wrapper_alias))\n            wrapper_model = create_model('TransientModel', __base__=OscalBaseModel, **dynamic_passer)\n            wrapped_model = wrapper_model.construct(**{self._wrapper_alias: self._elem})\n            json_data = wrapped_model.oscal_serialize_json(pretty=pretty, wrapped=False)\n    return json_data\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.to_yaml","title":"to_yaml(self)","text":"

                                    Convert into YAML string.

                                    Source code in trestle/core/models/elements.py
                                    def to_yaml(self) -> str:\n\"\"\"Convert into YAML string.\"\"\"\n    yaml = YAML(typ='safe')\n    yaml.default_flow_style = False\n    from io import StringIO\n    string_stream = StringIO()\n    yaml.dump(yaml.load(self.to_json(pretty=False)), string_stream)\n    yaml_data = string_stream.getvalue()\n    string_stream.close()\n\n    return yaml_data\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath","title":" ElementPath ","text":"

                                    Element path wrapper of an element.

                                    This only allows a single wildcard '*' at the end to denote elements of an array or dict

                                    Source code in trestle/core/models/elements.py
                                    class ElementPath:\n\"\"\"Element path wrapper of an element.\n\n    This only allows a single wildcard '*' at the end to denote elements of an array or dict\n    \"\"\"\n\n    PATH_SEPARATOR: str = const.ALIAS_PATH_SEPARATOR\n\n    WILDCARD: str = '*'\n\n    def __init__(self, element_path: str, parent_path: Optional['ElementPath'] = None) -> None:\n\"\"\"Initialize an element wrapper.\n\n        It assumes the element path contains oscal field alias with hyphens only\n        \"\"\"\n        self._parent_path = parent_path\n\n        self._path: List[str] = self._parse(element_path)\n\n        # Initialize private variables for lazy processing and caching\n        self._element_name: Optional[str] = None\n        self._preceding_path: Optional['ElementPath'] = None\n\n    def _parse(self, element_path: str) -> List[str]:\n\"\"\"Parse the element path and validate.\"\"\"\n        parts: List[str] = element_path.split(self.PATH_SEPARATOR)\n\n        for part in parts:\n            if part == '':\n                raise TrestleError(\n                    f'Invalid path \"{element_path}\" because there are empty path parts between \"{self.PATH_SEPARATOR}\" '\n                    'or in the beginning'\n                )\n\n        if parts[0] == self.WILDCARD:\n            raise TrestleError(f'Invalid path {element_path} with wildcard.')\n        return parts\n\n    def get(self) -> List[str]:\n\"\"\"Return the path parts as a list.\"\"\"\n        return self._path\n\n    def get_type(self, root_model: Optional[Type[Any]] = None, use_parent: bool = False) -> Type[Any]:\n\"\"\"Get the type of an element.\n\n        If possible the model type will be derived from one of the top level models,\n        otherwise a 'root model' can be passed for situations where this is not possible.\n\n        This type path should *NOT* have wild cards in it. It *may* have* indices.\n        Valid Examples:\n            catalog.metadata\n            catalog.groups\n            catalog.groups.group\n            catalog\n            catalog.groups.0\n\n        Args:\n            root_model: An OscalBaseModel Type from which to base the approach on.\n            use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n        Returns:\n            The type of the model whether or not it is an OscalBaseModel or not.\n        \"\"\"\n        effective_path: List[str]\n        if use_parent:\n            effective_path = self.get_full_path_parts()\n        else:\n            effective_path = self._path\n\n        if not root_model:\n            # lookup root model from top level oscal models or fail\n            prev_model = self._top_level_type_lookup(effective_path[0])\n        else:\n            prev_model = root_model\n        if len(effective_path) == 1:\n            return prev_model\n        # variables\n        # for current_element_str in effective_path[1:]:\n        for current_element_str in effective_path[1:]:\n            # Determine if the parent model is a collection.\n            if utils.is_collection_field_type(prev_model):\n                inner_model = utils.get_inner_type(prev_model)\n                inner_class_name = classname_to_alias(inner_model.__name__, AliasMode.JSON)\n                # Assert that the current name fits an expected form.\n                # Valid choices here are *, integer (for arrays) and the inner model alias\n                if (inner_class_name == current_element_str or current_element_str == self.WILDCARD\n                        or current_element_str.isnumeric()):\n                    prev_model = inner_model\n\n                else:\n                    raise TrestleError('Unexpected key in element path when finding type.')\n\n            else:\n                # Indices, * are not allowed on non-collection types\n                if current_element_str == self.WILDCARD:\n                    raise TrestleError(\n                        'Wild card in unexpected position when trying to find class type.'\n                        + ' Element path type lookup can only occur where a single type can be identified.'\n                    )\n                prev_model = prev_model.alias_to_field_map()[current_element_str].outer_type_\n        return prev_model\n\n    def get_obm_wrapped_type(self,\n                             root_model: Optional[Type[Any]] = None,\n                             use_parent: bool = False) -> Type[OscalBaseModel]:\n\"\"\"Get the type of the element. Wraps the collection type in an OscalBaseModel as a __root__ element.\n\n        This should principally be used for validating content.\n\n        Args:\n            root_model: An OscalBaseModel Type from which to base the approach on.\n            use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n        Returns:\n            The type of the model whether wrapped or not as an OscalBaseModel.\n        \"\"\"\n        base_type = self.get_type(root_model, use_parent)\n        # Get an outer model type.\n        origin_type = utils.get_origin(base_type)\n\n        if origin_type in [list, dict]:\n            # OSCAL does not support collections of collections directly. We should not hit this scenario\n            collection_name = self.get_last()\n            if collection_name == self.WILDCARD:\n                logger.critical('Unexpected error in type system when inferring type from element path.')\n                logger.critical('Please report this issue.')\n                raise TrestleError('Unknown error inferring type from element path.')\n            # Final path must be the alias\n\n            new_base_type = create_model(\n                str_utils.alias_to_classname(collection_name, AliasMode.JSON),\n                __base__=OscalBaseModel,\n                __root__=(base_type, ...)\n            )\n            return new_base_type\n        return base_type\n\n    def _top_level_type_lookup(self, element_str: str) -> Type[common_types.TopLevelOscalModel]:\n\"\"\"From an individual element tag, induce the type of the model.\n\n        Args:\n            element_str: individual element as text such as 'catalog' or 'profile'\n\n        Returns:\n            Top level object model such as catalog, profile etc.\n        \"\"\"\n        # Even though awkward use chain of models.\n        if element_str not in const.MODEL_TYPE_LIST:\n            raise TrestleError(f'{element_str} is not a top level model (e.g. catalog, profile)')\n        model_package = const.MODEL_TYPE_TO_MODEL_MODULE[element_str]\n        object_type, _ = ModelUtils.get_root_model(model_package)\n        object_type = cast(Type[common_types.TopLevelOscalModel], object_type)\n        return object_type\n\n    def is_multipart(self) -> bool:\n\"\"\"Assert whether or not an element path is multiple parts.\n\n        Originally element paths had to have multiple paths.\n        This provides a check for higher level code that still has that requirement.\n\n        Single part:\n            catalog\n            control\n            assessment-results\n\n        Multipart:\n            catalog.metadata\n            catalog.controls.control\n        \"\"\"\n        return len(self._path) > 1\n\n    def to_string(self) -> str:\n\"\"\"Return the path parts as a dot-separated string.\"\"\"\n        return self.PATH_SEPARATOR.join(self.get())\n\n    def get_parent(self) -> 'ElementPath':\n\"\"\"Return the parent path.\n\n        It can be None or a valid ElementPath\n        \"\"\"\n        return self._parent_path\n\n    def get_first(self) -> str:\n\"\"\"Return the first part of the path.\"\"\"\n        return self._path[0]\n\n    def get_last(self) -> str:\n\"\"\"Return the last part of the path.\"\"\"\n        return self._path[-1]\n\n    def get_full(self) -> str:\n\"\"\"Return the full path including parent path parts as a dot separated str.\"\"\"\n        all_parts = self.get_full_path_parts()\n        return self.PATH_SEPARATOR.join(all_parts)\n\n    def get_element_name(self) -> str:\n\"\"\"Return the element alias name from the path.\n\n        Essentailly this the last part of the element path\n        \"\"\"\n        # if it is available then return otherwise compute\n        if self._element_name is None:\n            element_name = self.get_last()\n            if element_name == self.WILDCARD:\n                element_name = self._path[-2]\n\n            self._element_name = element_name\n\n        return self._element_name\n\n    def get_full_path_parts(self) -> List[str]:\n\"\"\"Get full path parts to the element including parent path parts as a list.\"\"\"\n        path_parts = []\n        if self.get_parent() is not None:\n            parent_path_parts = self.get_parent().get_full_path_parts()\n            path_parts.extend(parent_path_parts)\n            path_parts.extend(self.get()[1:])  # don't use the first part\n        else:\n            path_parts.extend(self.get())\n\n        return path_parts\n\n    def get_preceding_path(self) -> 'ElementPath':\n\"\"\"Return the element path to the preceding element in the path.\"\"\"\n        # if it is available then return otherwise compute\n        if self._preceding_path is None:\n            path_parts = self.get_full_path_parts()\n\n            if len(path_parts) > 1:\n                prec_path_parts = path_parts[:-1]\n                self._preceding_path = ElementPath(self.PATH_SEPARATOR.join(prec_path_parts))\n\n        return self._preceding_path\n\n    def find_last_file_in_path(self, content_type: FileContentType, model_dir: pathlib.Path) -> pathlib.Path:\n\"\"\"Find the last (nearest) existing file in the element path leading to this element.\"\"\"\n        # model dir is the top level dir for this model, e.g. catalogs/mycat\n        path = model_dir\n        extension = FileContentType.to_file_extension(content_type)\n        good_model: pathlib.Path = None\n        for element in self._path:\n            if element == '*':\n                break\n            model_file = (path / element).with_suffix(extension)\n            if not model_file.exists():\n                break\n            path = path / element\n            good_model = model_file\n        return good_model\n\n    def make_absolute(self, model_dir: pathlib.Path, reference_dir: pathlib.Path):\n\"\"\"Make the parts absolute from the top model dir.\"\"\"\n        # Match the current relative element path to the model directory and reference directory\n        # If the element path is partial and doesn't connect to the top of the model,\n        # need to deduce absolute element path from the model_dir and the reference directory\n        # that corresponds to the root of the element path\n\n        # if first element is a model type it is already absolute\n        if self._path[0] not in const.MODEL_TYPE_LIST:\n            rel_path = list(reference_dir.relative_to(model_dir).parts)\n            rel_path.extend(self._path)\n            self._path = rel_path\n\n    def make_relative(self, model_relative_path: pathlib.Path) -> int:\n\"\"\"Make the parts relative to the model path.\"\"\"\n        # The element path should currently be absolute\n        # The model relative path should be relative to the top leve of the model\n        # Change the element path to be relative to the model being loaded\n        # Returns 0 on success and 1 on failur\n        rel_path_parts = model_relative_path.parts[:-1]\n        n_rel_parts = len(rel_path_parts)\n        # the element path can't start above the model path\n        if n_rel_parts >= len(self._path):\n            return 1\n        # confirm the leading parts match\n        for ii in range(n_rel_parts):\n            if rel_path_parts[ii] != self._path[ii]:\n                return 1\n        # chop off the leading parts of the absolute element path\n        self._path = self._path[n_rel_parts:]\n        return 0\n\n    def to_file_path(self, content_type: FileContentType = None, root_dir: str = '') -> pathlib.Path:\n\"\"\"Convert to a file or directory path for the element path.\n\n        if content_type is not passed, it will return a path for directory\n        \"\"\"\n        path_parts = self.get()\n\n        # skip wildcard\n        if path_parts[-1] == ElementPath.WILDCARD:\n            path_parts = path_parts[:-1]\n\n        if root_dir != '':\n            path_parts[0] = root_dir\n\n        path_str = '/'.join(path_parts)\n\n        # add file extension if required\n        # this will be omitted if it is a dir path\n        if content_type is not None:\n            file_extension = FileContentType.to_file_extension(content_type)\n            path_str = path_str + file_extension\n\n        # prepare the path\n        file_path: pathlib.Path = pathlib.Path(f'./{path_str}')\n\n        return file_path\n\n    def to_root_path(self, content_type: FileContentType = None) -> pathlib.Path:\n\"\"\"Convert to a file path for the element root.\"\"\"\n        path_str = f'./{self.get_first()}'\n        if content_type is not None:\n            file_extension = FileContentType.to_file_extension(content_type)\n            path_str = path_str + file_extension\n\n        file_path: pathlib.Path = pathlib.Path(path_str)\n        return file_path\n\n    def __str__(self) -> str:\n\"\"\"Return string representation of element path.\"\"\"\n        return self.to_string()\n\n    def __eq__(self, other) -> bool:\n\"\"\"Override equality method.\"\"\"\n        if not isinstance(other, ElementPath):\n            return False\n\n        return self.get() == other.get()\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.PATH_SEPARATOR","title":"PATH_SEPARATOR: str","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.WILDCARD","title":"WILDCARD: str","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.__eq__","title":"__eq__(self, other) special","text":"

                                    Override equality method.

                                    Source code in trestle/core/models/elements.py
                                    def __eq__(self, other) -> bool:\n\"\"\"Override equality method.\"\"\"\n    if not isinstance(other, ElementPath):\n        return False\n\n    return self.get() == other.get()\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.__init__","title":"__init__(self, element_path, parent_path=None) special","text":"

                                    Initialize an element wrapper.

                                    It assumes the element path contains oscal field alias with hyphens only

                                    Source code in trestle/core/models/elements.py
                                    def __init__(self, element_path: str, parent_path: Optional['ElementPath'] = None) -> None:\n\"\"\"Initialize an element wrapper.\n\n    It assumes the element path contains oscal field alias with hyphens only\n    \"\"\"\n    self._parent_path = parent_path\n\n    self._path: List[str] = self._parse(element_path)\n\n    # Initialize private variables for lazy processing and caching\n    self._element_name: Optional[str] = None\n    self._preceding_path: Optional['ElementPath'] = None\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.__str__","title":"__str__(self) special","text":"

                                    Return string representation of element path.

                                    Source code in trestle/core/models/elements.py
                                    def __str__(self) -> str:\n\"\"\"Return string representation of element path.\"\"\"\n    return self.to_string()\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.find_last_file_in_path","title":"find_last_file_in_path(self, content_type, model_dir)","text":"

                                    Find the last (nearest) existing file in the element path leading to this element.

                                    Source code in trestle/core/models/elements.py
                                    def find_last_file_in_path(self, content_type: FileContentType, model_dir: pathlib.Path) -> pathlib.Path:\n\"\"\"Find the last (nearest) existing file in the element path leading to this element.\"\"\"\n    # model dir is the top level dir for this model, e.g. catalogs/mycat\n    path = model_dir\n    extension = FileContentType.to_file_extension(content_type)\n    good_model: pathlib.Path = None\n    for element in self._path:\n        if element == '*':\n            break\n        model_file = (path / element).with_suffix(extension)\n        if not model_file.exists():\n            break\n        path = path / element\n        good_model = model_file\n    return good_model\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get","title":"get(self)","text":"

                                    Return the path parts as a list.

                                    Source code in trestle/core/models/elements.py
                                    def get(self) -> List[str]:\n\"\"\"Return the path parts as a list.\"\"\"\n    return self._path\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_element_name","title":"get_element_name(self)","text":"

                                    Return the element alias name from the path.

                                    Essentailly this the last part of the element path

                                    Source code in trestle/core/models/elements.py
                                    def get_element_name(self) -> str:\n\"\"\"Return the element alias name from the path.\n\n    Essentailly this the last part of the element path\n    \"\"\"\n    # if it is available then return otherwise compute\n    if self._element_name is None:\n        element_name = self.get_last()\n        if element_name == self.WILDCARD:\n            element_name = self._path[-2]\n\n        self._element_name = element_name\n\n    return self._element_name\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_first","title":"get_first(self)","text":"

                                    Return the first part of the path.

                                    Source code in trestle/core/models/elements.py
                                    def get_first(self) -> str:\n\"\"\"Return the first part of the path.\"\"\"\n    return self._path[0]\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_full","title":"get_full(self)","text":"

                                    Return the full path including parent path parts as a dot separated str.

                                    Source code in trestle/core/models/elements.py
                                    def get_full(self) -> str:\n\"\"\"Return the full path including parent path parts as a dot separated str.\"\"\"\n    all_parts = self.get_full_path_parts()\n    return self.PATH_SEPARATOR.join(all_parts)\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_full_path_parts","title":"get_full_path_parts(self)","text":"

                                    Get full path parts to the element including parent path parts as a list.

                                    Source code in trestle/core/models/elements.py
                                    def get_full_path_parts(self) -> List[str]:\n\"\"\"Get full path parts to the element including parent path parts as a list.\"\"\"\n    path_parts = []\n    if self.get_parent() is not None:\n        parent_path_parts = self.get_parent().get_full_path_parts()\n        path_parts.extend(parent_path_parts)\n        path_parts.extend(self.get()[1:])  # don't use the first part\n    else:\n        path_parts.extend(self.get())\n\n    return path_parts\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_last","title":"get_last(self)","text":"

                                    Return the last part of the path.

                                    Source code in trestle/core/models/elements.py
                                    def get_last(self) -> str:\n\"\"\"Return the last part of the path.\"\"\"\n    return self._path[-1]\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_obm_wrapped_type","title":"get_obm_wrapped_type(self, root_model=None, use_parent=False)","text":"

                                    Get the type of the element. Wraps the collection type in an OscalBaseModel as a root element.

                                    This should principally be used for validating content.

                                    Parameters:

                                    Name Type Description Default root_model Optional[Type[Any]]

                                    An OscalBaseModel Type from which to base the approach on.

                                    None use_parent bool

                                    Whether or not to normalise the full path across parent ElementPaths, default to not.

                                    False

                                    Returns:

                                    Type Description Type[trestle.core.base_model.OscalBaseModel]

                                    The type of the model whether wrapped or not as an OscalBaseModel.

                                    Source code in trestle/core/models/elements.py
                                    def get_obm_wrapped_type(self,\n                         root_model: Optional[Type[Any]] = None,\n                         use_parent: bool = False) -> Type[OscalBaseModel]:\n\"\"\"Get the type of the element. Wraps the collection type in an OscalBaseModel as a __root__ element.\n\n    This should principally be used for validating content.\n\n    Args:\n        root_model: An OscalBaseModel Type from which to base the approach on.\n        use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n    Returns:\n        The type of the model whether wrapped or not as an OscalBaseModel.\n    \"\"\"\n    base_type = self.get_type(root_model, use_parent)\n    # Get an outer model type.\n    origin_type = utils.get_origin(base_type)\n\n    if origin_type in [list, dict]:\n        # OSCAL does not support collections of collections directly. We should not hit this scenario\n        collection_name = self.get_last()\n        if collection_name == self.WILDCARD:\n            logger.critical('Unexpected error in type system when inferring type from element path.')\n            logger.critical('Please report this issue.')\n            raise TrestleError('Unknown error inferring type from element path.')\n        # Final path must be the alias\n\n        new_base_type = create_model(\n            str_utils.alias_to_classname(collection_name, AliasMode.JSON),\n            __base__=OscalBaseModel,\n            __root__=(base_type, ...)\n        )\n        return new_base_type\n    return base_type\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_parent","title":"get_parent(self)","text":"

                                    Return the parent path.

                                    It can be None or a valid ElementPath

                                    Source code in trestle/core/models/elements.py
                                    def get_parent(self) -> 'ElementPath':\n\"\"\"Return the parent path.\n\n    It can be None or a valid ElementPath\n    \"\"\"\n    return self._parent_path\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_preceding_path","title":"get_preceding_path(self)","text":"

                                    Return the element path to the preceding element in the path.

                                    Source code in trestle/core/models/elements.py
                                    def get_preceding_path(self) -> 'ElementPath':\n\"\"\"Return the element path to the preceding element in the path.\"\"\"\n    # if it is available then return otherwise compute\n    if self._preceding_path is None:\n        path_parts = self.get_full_path_parts()\n\n        if len(path_parts) > 1:\n            prec_path_parts = path_parts[:-1]\n            self._preceding_path = ElementPath(self.PATH_SEPARATOR.join(prec_path_parts))\n\n    return self._preceding_path\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_type","title":"get_type(self, root_model=None, use_parent=False)","text":"

                                    Get the type of an element.

                                    If possible the model type will be derived from one of the top level models, otherwise a 'root model' can be passed for situations where this is not possible.

                                    This type path should NOT have wild cards in it. It may have* indices. Valid Examples: catalog.metadata catalog.groups catalog.groups.group catalog catalog.groups.0

                                    Parameters:

                                    Name Type Description Default root_model Optional[Type[Any]]

                                    An OscalBaseModel Type from which to base the approach on.

                                    None use_parent bool

                                    Whether or not to normalise the full path across parent ElementPaths, default to not.

                                    False

                                    Returns:

                                    Type Description Type[Any]

                                    The type of the model whether or not it is an OscalBaseModel or not.

                                    Source code in trestle/core/models/elements.py
                                    def get_type(self, root_model: Optional[Type[Any]] = None, use_parent: bool = False) -> Type[Any]:\n\"\"\"Get the type of an element.\n\n    If possible the model type will be derived from one of the top level models,\n    otherwise a 'root model' can be passed for situations where this is not possible.\n\n    This type path should *NOT* have wild cards in it. It *may* have* indices.\n    Valid Examples:\n        catalog.metadata\n        catalog.groups\n        catalog.groups.group\n        catalog\n        catalog.groups.0\n\n    Args:\n        root_model: An OscalBaseModel Type from which to base the approach on.\n        use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n    Returns:\n        The type of the model whether or not it is an OscalBaseModel or not.\n    \"\"\"\n    effective_path: List[str]\n    if use_parent:\n        effective_path = self.get_full_path_parts()\n    else:\n        effective_path = self._path\n\n    if not root_model:\n        # lookup root model from top level oscal models or fail\n        prev_model = self._top_level_type_lookup(effective_path[0])\n    else:\n        prev_model = root_model\n    if len(effective_path) == 1:\n        return prev_model\n    # variables\n    # for current_element_str in effective_path[1:]:\n    for current_element_str in effective_path[1:]:\n        # Determine if the parent model is a collection.\n        if utils.is_collection_field_type(prev_model):\n            inner_model = utils.get_inner_type(prev_model)\n            inner_class_name = classname_to_alias(inner_model.__name__, AliasMode.JSON)\n            # Assert that the current name fits an expected form.\n            # Valid choices here are *, integer (for arrays) and the inner model alias\n            if (inner_class_name == current_element_str or current_element_str == self.WILDCARD\n                    or current_element_str.isnumeric()):\n                prev_model = inner_model\n\n            else:\n                raise TrestleError('Unexpected key in element path when finding type.')\n\n        else:\n            # Indices, * are not allowed on non-collection types\n            if current_element_str == self.WILDCARD:\n                raise TrestleError(\n                    'Wild card in unexpected position when trying to find class type.'\n                    + ' Element path type lookup can only occur where a single type can be identified.'\n                )\n            prev_model = prev_model.alias_to_field_map()[current_element_str].outer_type_\n    return prev_model\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.is_multipart","title":"is_multipart(self)","text":"

                                    Assert whether or not an element path is multiple parts.

                                    Originally element paths had to have multiple paths. This provides a check for higher level code that still has that requirement.

                                    Single part: catalog control assessment-results

                                    Multipart

                                    catalog.metadata catalog.controls.control

                                    Source code in trestle/core/models/elements.py
                                    def is_multipart(self) -> bool:\n\"\"\"Assert whether or not an element path is multiple parts.\n\n    Originally element paths had to have multiple paths.\n    This provides a check for higher level code that still has that requirement.\n\n    Single part:\n        catalog\n        control\n        assessment-results\n\n    Multipart:\n        catalog.metadata\n        catalog.controls.control\n    \"\"\"\n    return len(self._path) > 1\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.make_absolute","title":"make_absolute(self, model_dir, reference_dir)","text":"

                                    Make the parts absolute from the top model dir.

                                    Source code in trestle/core/models/elements.py
                                    def make_absolute(self, model_dir: pathlib.Path, reference_dir: pathlib.Path):\n\"\"\"Make the parts absolute from the top model dir.\"\"\"\n    # Match the current relative element path to the model directory and reference directory\n    # If the element path is partial and doesn't connect to the top of the model,\n    # need to deduce absolute element path from the model_dir and the reference directory\n    # that corresponds to the root of the element path\n\n    # if first element is a model type it is already absolute\n    if self._path[0] not in const.MODEL_TYPE_LIST:\n        rel_path = list(reference_dir.relative_to(model_dir).parts)\n        rel_path.extend(self._path)\n        self._path = rel_path\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.make_relative","title":"make_relative(self, model_relative_path)","text":"

                                    Make the parts relative to the model path.

                                    Source code in trestle/core/models/elements.py
                                    def make_relative(self, model_relative_path: pathlib.Path) -> int:\n\"\"\"Make the parts relative to the model path.\"\"\"\n    # The element path should currently be absolute\n    # The model relative path should be relative to the top leve of the model\n    # Change the element path to be relative to the model being loaded\n    # Returns 0 on success and 1 on failur\n    rel_path_parts = model_relative_path.parts[:-1]\n    n_rel_parts = len(rel_path_parts)\n    # the element path can't start above the model path\n    if n_rel_parts >= len(self._path):\n        return 1\n    # confirm the leading parts match\n    for ii in range(n_rel_parts):\n        if rel_path_parts[ii] != self._path[ii]:\n            return 1\n    # chop off the leading parts of the absolute element path\n    self._path = self._path[n_rel_parts:]\n    return 0\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.to_file_path","title":"to_file_path(self, content_type=None, root_dir='')","text":"

                                    Convert to a file or directory path for the element path.

                                    if content_type is not passed, it will return a path for directory

                                    Source code in trestle/core/models/elements.py
                                    def to_file_path(self, content_type: FileContentType = None, root_dir: str = '') -> pathlib.Path:\n\"\"\"Convert to a file or directory path for the element path.\n\n    if content_type is not passed, it will return a path for directory\n    \"\"\"\n    path_parts = self.get()\n\n    # skip wildcard\n    if path_parts[-1] == ElementPath.WILDCARD:\n        path_parts = path_parts[:-1]\n\n    if root_dir != '':\n        path_parts[0] = root_dir\n\n    path_str = '/'.join(path_parts)\n\n    # add file extension if required\n    # this will be omitted if it is a dir path\n    if content_type is not None:\n        file_extension = FileContentType.to_file_extension(content_type)\n        path_str = path_str + file_extension\n\n    # prepare the path\n    file_path: pathlib.Path = pathlib.Path(f'./{path_str}')\n\n    return file_path\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.to_root_path","title":"to_root_path(self, content_type=None)","text":"

                                    Convert to a file path for the element root.

                                    Source code in trestle/core/models/elements.py
                                    def to_root_path(self, content_type: FileContentType = None) -> pathlib.Path:\n\"\"\"Convert to a file path for the element root.\"\"\"\n    path_str = f'./{self.get_first()}'\n    if content_type is not None:\n        file_extension = FileContentType.to_file_extension(content_type)\n        path_str = path_str + file_extension\n\n    file_path: pathlib.Path = pathlib.Path(path_str)\n    return file_path\n
                                    "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.to_string","title":"to_string(self)","text":"

                                    Return the path parts as a dot-separated string.

                                    Source code in trestle/core/models/elements.py
                                    def to_string(self) -> str:\n\"\"\"Return the path parts as a dot-separated string.\"\"\"\n    return self.PATH_SEPARATOR.join(self.get())\n
                                    "},{"location":"api_reference/trestle.core.models.file_content_type/","title":"file_content_type","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type","title":"trestle.core.models.file_content_type","text":"

                                    Action wrapper of a command.

                                    "},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType","title":" FileContentType (Enum) ","text":"

                                    File Content type for read/write.

                                    Source code in trestle/core/models/file_content_type.py
                                    class FileContentType(Enum):\n\"\"\"File Content type for read/write.\"\"\"\n\n    # JSON formatted content\n    JSON = 1\n\n    # YAML formatted content\n    YAML = 2\n\n    # No extension and possibly a DIR\n    DIRLIKE = 3\n\n    # Type could not be determined\n    UNKNOWN = 4\n\n    @classmethod\n    def to_file_extension(cls, content_type: 'FileContentType') -> str:\n\"\"\"Get file extension for the type, including the dot.\"\"\"\n        if content_type == FileContentType.YAML:\n            return '.yaml'\n        if content_type == FileContentType.JSON:\n            return '.json'\n        raise TrestleError(f'Invalid file content type {content_type}')\n\n    @classmethod\n    def to_content_type(cls, file_extension: str) -> 'FileContentType':\n\"\"\"Get content type form file extension, including the dot.\"\"\"\n        if file_extension == '.json':\n            return FileContentType.JSON\n        if file_extension == '.yaml' or file_extension == '.yml':\n            return FileContentType.YAML\n        if not file_extension:\n            return FileContentType.DIRLIKE\n\n        raise TrestleError(f'Unsupported file extension {file_extension}')\n\n    @classmethod\n    def path_to_content_type(cls, file_path: Path) -> 'FileContentType':\n\"\"\"Get content type from file path looking for extension.\"\"\"\n        if file_path.with_suffix('.json').exists():\n            return FileContentType.JSON\n        if file_path.with_suffix('.yaml').exists():\n            return FileContentType.YAML\n        if file_path.with_suffix('.yml').exists():\n            return FileContentType.YAML\n        return FileContentType.UNKNOWN\n\n    @classmethod\n    def dir_to_content_type(cls, dir_path: Path) -> 'FileContentType':\n\"\"\"Get content type by looking for json or yaml files in dir.\"\"\"\n        files = dir_path.glob('*')\n        for file in files:\n            if file.is_file():\n                suffix = file.suffix\n                if suffix == '.json':\n                    return FileContentType.JSON\n                if suffix in ['.yaml', '.yml']:\n                    return FileContentType.YAML\n        return FileContentType.UNKNOWN\n\n    @classmethod\n    def path_to_file_extension(cls, file_path: Path) -> str:\n\"\"\"Get extension from file path looking for extension.\"\"\"\n        if file_path.with_suffix('.json').exists():\n            return '.json'\n        if file_path.with_suffix('.yaml').exists():\n            return '.yaml'\n        if file_path.with_suffix('.yml').exists():\n            return '.yml'\n        return ''\n\n    @classmethod\n    def is_readable_file(cls, content_type: 'FileContentType') -> bool:\n\"\"\"Is the file a type that can be read directly.\"\"\"\n        return content_type == FileContentType.JSON or content_type == FileContentType.YAML\n
                                    "},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.DIRLIKE","title":"DIRLIKE","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.JSON","title":"JSON","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.UNKNOWN","title":"UNKNOWN","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.YAML","title":"YAML","text":""},{"location":"api_reference/trestle.core.models.interfaces/","title":"interfaces","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces","title":"trestle.core.models.interfaces","text":"

                                    Interfaces for use within other trestle functions defined as pydantic data models.

                                    "},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly","title":" OSCALAssembly (TrestleBaseModel) pydantic-model","text":"

                                    Data model to represent an assembled set of OSCAL objects.

                                    Here the assembly represents the constraints as expected by the current OSCAL schema. At this point in time a 'flat' model has been chosen rather than an tree.

                                    Source code in trestle/core/models/interfaces.py
                                    class OSCALAssembly(TrestleBaseModel):\n\"\"\"Data model to represent an assembled set of OSCAL objects.\n\n    Here the assembly represents the constraints as expected by the current OSCAL\n    schema. At this point in time a 'flat' model has been chosen rather than an tree.\n    \"\"\"\n\n    poam: Optional[o_poam.PlanOfActionAndMilestones] = None\n    sar: Optional[o_ar.AssessmentResults] = None\n    sap: Optional[o_ap.AssessmentPlan] = None\n    ssp: Optional[o_ssp.SystemSecurityPlan] = None\n    profiles: Optional[Dict[str, o_profile.Profile]] = None\n    catalogs: Optional[Dict[str, o_catalog.Catalog]] = None\n    components: Optional[Dict[str, o_component.ComponentDefinition]] = None\n\n    class Config:\n\"\"\"Pydantic config overrides.\"\"\"\n\n        allow_population_by_field_name = True\n        # Enforce strict schema\n        extra = Extra.forbid\n        # Validate on assignment of variables to ensure no escapes\n        validate_assignment = True\n
                                    "},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.catalogs","title":"catalogs: Dict[str, trestle.oscal.catalog.Catalog] pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.components","title":"components: Dict[str, trestle.oscal.component.ComponentDefinition] pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.poam","title":"poam: PlanOfActionAndMilestones pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.profiles","title":"profiles: Dict[str, trestle.oscal.profile.Profile] pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.sap","title":"sap: AssessmentPlan pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.sar","title":"sar: AssessmentResults pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.ssp","title":"ssp: SystemSecurityPlan pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.Config","title":" Config ","text":"

                                    Pydantic config overrides.

                                    Source code in trestle/core/models/interfaces.py
                                    class Config:\n\"\"\"Pydantic config overrides.\"\"\"\n\n    allow_population_by_field_name = True\n    # Enforce strict schema\n    extra = Extra.forbid\n    # Validate on assignment of variables to ensure no escapes\n    validate_assignment = True\n
                                    allow_population_by_field_name \u00a4 extra \u00a4 validate_assignment \u00a4"},{"location":"api_reference/trestle.core.models.plans/","title":"plans","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans","title":"trestle.core.models.plans","text":"

                                    Plan of action of a command.

                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan","title":" Plan ","text":"

                                    Plan of action of a command.

                                    Source code in trestle/core/models/plans.py
                                    class Plan:\n\"\"\"Plan of action of a command.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize a plan.\"\"\"\n        self._actions: List[Action] = []\n\n    def _action_key(self, action: Action) -> int:\n        return hash(action)\n\n    def __str__(self) -> str:\n\"\"\"Print the plan.\"\"\"\n        list_actions = []\n        index = 1\n        for action in self._actions:\n            list_actions.append(f'{index}. {action}')\n            index = index + 1\n\n        list_str = '\\n'.join(list_actions)\n        return list_str\n\n    def get_actions(self) -> List[Action]:\n\"\"\"Get all actions.\"\"\"\n        return self._actions\n\n    def add_action(self, action: Action) -> None:\n\"\"\"Add a new action.\"\"\"\n        self._actions.append(action)\n\n    def add_actions(self, actions: List[Action]) -> None:\n\"\"\"Add actions in order.\"\"\"\n        self._actions.extend(actions)\n\n    def clear_actions(self) -> None:\n\"\"\"Clear all actions.\"\"\"\n        self._actions = []\n\n    def execute(self) -> None:\n\"\"\"Execute the actions in the plan.\"\"\"\n        for action in self._actions:\n            try:\n                action.execute()\n            except Exception as e:\n                logger.error(f'Failed to execute action {action} for the plan: {e}. Rolling back.')\n                self.rollback()\n                raise e\n\n    def rollback(self) -> None:\n\"\"\"Rollback the actions in the plan.\"\"\"\n        # execute in reverse order\n        for action in reversed(self._actions):\n            if action.has_rollback() is False:\n                raise UnsupportedOperation(f'{action.get_type()} does not support rollback')\n            action.rollback()\n\n    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two plans are equal.\"\"\"\n        if not isinstance(other, Plan):\n            return False\n\n        return self.get_actions() == other.get_actions()\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.__eq__","title":"__eq__(self, other) special","text":"

                                    Check that two plans are equal.

                                    Source code in trestle/core/models/plans.py
                                    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two plans are equal.\"\"\"\n    if not isinstance(other, Plan):\n        return False\n\n    return self.get_actions() == other.get_actions()\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.__init__","title":"__init__(self) special","text":"

                                    Initialize a plan.

                                    Source code in trestle/core/models/plans.py
                                    def __init__(self) -> None:\n\"\"\"Initialize a plan.\"\"\"\n    self._actions: List[Action] = []\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.__str__","title":"__str__(self) special","text":"

                                    Print the plan.

                                    Source code in trestle/core/models/plans.py
                                    def __str__(self) -> str:\n\"\"\"Print the plan.\"\"\"\n    list_actions = []\n    index = 1\n    for action in self._actions:\n        list_actions.append(f'{index}. {action}')\n        index = index + 1\n\n    list_str = '\\n'.join(list_actions)\n    return list_str\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.add_action","title":"add_action(self, action)","text":"

                                    Add a new action.

                                    Source code in trestle/core/models/plans.py
                                    def add_action(self, action: Action) -> None:\n\"\"\"Add a new action.\"\"\"\n    self._actions.append(action)\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.add_actions","title":"add_actions(self, actions)","text":"

                                    Add actions in order.

                                    Source code in trestle/core/models/plans.py
                                    def add_actions(self, actions: List[Action]) -> None:\n\"\"\"Add actions in order.\"\"\"\n    self._actions.extend(actions)\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.clear_actions","title":"clear_actions(self)","text":"

                                    Clear all actions.

                                    Source code in trestle/core/models/plans.py
                                    def clear_actions(self) -> None:\n\"\"\"Clear all actions.\"\"\"\n    self._actions = []\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.execute","title":"execute(self)","text":"

                                    Execute the actions in the plan.

                                    Source code in trestle/core/models/plans.py
                                    def execute(self) -> None:\n\"\"\"Execute the actions in the plan.\"\"\"\n    for action in self._actions:\n        try:\n            action.execute()\n        except Exception as e:\n            logger.error(f'Failed to execute action {action} for the plan: {e}. Rolling back.')\n            self.rollback()\n            raise e\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.get_actions","title":"get_actions(self)","text":"

                                    Get all actions.

                                    Source code in trestle/core/models/plans.py
                                    def get_actions(self) -> List[Action]:\n\"\"\"Get all actions.\"\"\"\n    return self._actions\n
                                    "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.rollback","title":"rollback(self)","text":"

                                    Rollback the actions in the plan.

                                    Source code in trestle/core/models/plans.py
                                    def rollback(self) -> None:\n\"\"\"Rollback the actions in the plan.\"\"\"\n    # execute in reverse order\n    for action in reversed(self._actions):\n        if action.has_rollback() is False:\n            raise UnsupportedOperation(f'{action.get_type()} does not support rollback')\n        action.rollback()\n
                                    "},{"location":"api_reference/trestle.core.object_factory/","title":"object_factory","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory","title":"trestle.core.object_factory","text":"

                                    Generic object factory.

                                    "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory","title":" ObjectFactory ","text":"

                                    Allow registration and creation of factory objects.

                                    Source code in trestle/core/object_factory.py
                                    class ObjectFactory:\n\"\"\"Allow registration and creation of factory objects.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize the objects dictionary as empty.\"\"\"\n        self._objects: Dict[str, Any] = {}\n\n    def register_object(self, mode: str, obj: Any) -> None:\n\"\"\"Register an object to the object factory.\n\n        Args:\n            mode: Descriptive key for the mode / type of object to be retrieved.\n            obj: The object type to be registered.\n        \"\"\"\n        self._objects[mode] = obj\n\n    def get(self, args: argparse.Namespace) -> Any:\n\"\"\"Create the object from the args.\"\"\"\n        return self._objects.get(args.mode)\n\n    def get_all(self) -> ValuesView[Any]:\n\"\"\"Get all registered objects.\"\"\"\n        return self._objects.values()\n
                                    "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.__init__","title":"__init__(self) special","text":"

                                    Initialize the objects dictionary as empty.

                                    Source code in trestle/core/object_factory.py
                                    def __init__(self) -> None:\n\"\"\"Initialize the objects dictionary as empty.\"\"\"\n    self._objects: Dict[str, Any] = {}\n
                                    "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.get","title":"get(self, args)","text":"

                                    Create the object from the args.

                                    Source code in trestle/core/object_factory.py
                                    def get(self, args: argparse.Namespace) -> Any:\n\"\"\"Create the object from the args.\"\"\"\n    return self._objects.get(args.mode)\n
                                    "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.get_all","title":"get_all(self)","text":"

                                    Get all registered objects.

                                    Source code in trestle/core/object_factory.py
                                    def get_all(self) -> ValuesView[Any]:\n\"\"\"Get all registered objects.\"\"\"\n    return self._objects.values()\n
                                    "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.register_object","title":"register_object(self, mode, obj)","text":"

                                    Register an object to the object factory.

                                    Parameters:

                                    Name Type Description Default mode str

                                    Descriptive key for the mode / type of object to be retrieved.

                                    required obj Any

                                    The object type to be registered.

                                    required Source code in trestle/core/object_factory.py
                                    def register_object(self, mode: str, obj: Any) -> None:\n\"\"\"Register an object to the object factory.\n\n    Args:\n        mode: Descriptive key for the mode / type of object to be retrieved.\n        obj: The object type to be registered.\n    \"\"\"\n    self._objects[mode] = obj\n
                                    "},{"location":"api_reference/trestle.core.parser/","title":"parser","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser","title":"trestle.core.parser","text":"

                                    Model parsing for use when models themselves must be inferred and are not known.

                                    Under most use cases trestle.core.base_model.OscalBaseModel provides functionality for loading Oscal models from files. However, under some circumstances the model internals are unknown. Use of this module should be avoided unless the BaseModel functionality is inadequate.

                                    "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.parser/#trestle.core.parser-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.parse_dict","title":"parse_dict(data, model_name)","text":"

                                    Load a model from the data dict.

                                    This functionality is provided for situations when the OSCAL data type is not known ahead of time. Here the model has been loaded into memory using json loads or similar and passed as a dict.

                                    Parameters:

                                    Name Type Description Default data Dict[str, Any]

                                    Oscal data loaded into memory as a dictionary with the root key removed.

                                    required model_name str

                                    should be of the form 'module.class' from trestle.oscal.* modules

                                    required

                                    Returns:

                                    Type Description OscalBaseModel

                                    The oscal model of the desired model.

                                    Source code in trestle/core/parser.py
                                    def parse_dict(data: Dict[str, Any], model_name: str) -> OscalBaseModel:\n\"\"\"Load a model from the data dict.\n\n    This functionality is provided for situations when the OSCAL data type is not known ahead of time. Here the model\n    has been loaded into memory using json loads or similar and passed as a dict.\n\n    Args:\n        data: Oscal data loaded into memory as a dictionary with the `root key` removed.\n        model_name: should be of the form 'module.class' from trestle.oscal.* modules\n\n    Returns:\n        The oscal model of the desired model.\n    \"\"\"\n    if data is None:\n        raise TrestleError('data name is required')\n\n    if model_name is None:\n        raise TrestleError('model_name is required')\n\n    parts = model_name.split('.')\n    class_name = parts.pop()\n    module_name = '.'.join(parts)\n\n    logger.debug(f'Loading class \"{class_name}\" from \"{module_name}\"')\n    module = importlib.import_module(module_name)\n    mclass: OscalBaseModel = getattr(module, class_name)\n    if mclass is None:\n        raise TrestleError(f'class \"{class_name}\" could not be found in \"{module_name}\"')\n\n    instance = mclass.parse_obj(data)\n    return instance\n
                                    "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.root_key","title":"root_key(data)","text":"

                                    Find root model name in the data.

                                    Source code in trestle/core/parser.py
                                    def root_key(data: Dict[str, Any]) -> str:\n\"\"\"Find root model name in the data.\"\"\"\n    if len(data.items()) == 1:\n        return next(iter(data))\n\n    raise TrestleError('data does not contain a root key')\n
                                    "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.to_full_model_name","title":"to_full_model_name(root_key)","text":"

                                    Find model name from the root_key in the file.

                                    Parameters:

                                    Name Type Description Default root_key str

                                    root key such as 'system-security-plan' from a top level OSCAL model.

                                    required Source code in trestle/core/parser.py
                                    def to_full_model_name(root_key: str) -> str:\n\"\"\"\n    Find model name from the root_key in the file.\n\n    Args:\n        root_key: root key such as 'system-security-plan' from a top level OSCAL model.\n    \"\"\"\n    if root_key not in const.MODEL_TYPE_LIST:\n        raise TrestleError(f'{root_key} is not a top level model name.')\n\n    module = const.MODEL_TYPE_TO_MODEL_MODULE[root_key]\n    class_name = alias_to_classname(root_key, AliasMode.JSON)\n    return f'{module}.{class_name}'\n
                                    "},{"location":"api_reference/trestle.core.pipeline/","title":"pipeline","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline","title":"trestle.core.pipeline","text":"

                                    Abstract base class for pipelines and filters.

                                    "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline","title":" Pipeline ","text":"

                                    Pipeline base class.

                                    Source code in trestle/core/pipeline.py
                                    class Pipeline():\n\"\"\"Pipeline base class.\"\"\"\n\n    class Filter(ABC):\n\"\"\"Filter class used by pipeline.\"\"\"\n\n        @abstractclassmethod\n        def process(self, input_: Any) -> Any:\n\"\"\"Process the input to output.\"\"\"\n            return input_\n\n    def __init__(self, filters: List[Filter]) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self._filters = filters\n\n    def process(self, input_: Any) -> Any:\n\"\"\"Process the filter pipeline.\"\"\"\n        for filter_ in self._filters:\n            input_ = filter_.process(input_)\n        return input_\n
                                    "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline.Filter","title":" Filter (ABC) ","text":"

                                    Filter class used by pipeline.

                                    Source code in trestle/core/pipeline.py
                                    class Filter(ABC):\n\"\"\"Filter class used by pipeline.\"\"\"\n\n    @abstractclassmethod\n    def process(self, input_: Any) -> Any:\n\"\"\"Process the input to output.\"\"\"\n        return input_\n
                                    Methods\u00a4 process(input_) classmethod \u00a4

                                    Process the input to output.

                                    Source code in trestle/core/pipeline.py
                                    @abstractclassmethod\ndef process(self, input_: Any) -> Any:\n\"\"\"Process the input to output.\"\"\"\n    return input_\n
                                    "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline.__init__","title":"__init__(self, filters) special","text":"

                                    Initialize the class.

                                    Source code in trestle/core/pipeline.py
                                    def __init__(self, filters: List[Filter]) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self._filters = filters\n
                                    "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline.process","title":"process(self, input_)","text":"

                                    Process the filter pipeline.

                                    Source code in trestle/core/pipeline.py
                                    def process(self, input_: Any) -> Any:\n\"\"\"Process the filter pipeline.\"\"\"\n    for filter_ in self._filters:\n        input_ = filter_.process(input_)\n    return input_\n
                                    "},{"location":"api_reference/trestle.core.profile_resolver/","title":"profile_resolver","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver","title":"trestle.core.profile_resolver","text":"

                                    Create resolved catalog from profile.

                                    "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver","title":" ProfileResolver ","text":"

                                    Class to resolve a catalog given a profile.

                                    Source code in trestle/core/profile_resolver.py
                                    class ProfileResolver():\n\"\"\"Class to resolve a catalog given a profile.\"\"\"\n\n    @staticmethod\n    def _extract_inherited_props(res_cat: cat.Catalog) -> Tuple[cat.Catalog, Dict[str, Any]]:\n\"\"\"\n        Build the control dict of inherited props.\n\n        Args:\n            The resolved profile catalog with a possible temporary part in each control\n\n        Returns:\n            The temporary parts are removed from each control and a Dict of added props per control_id is returned\n\n        Notes:\n        If an upstream profile adds props to the control they are tracked in a special temporary part in the control\n        called const.TRESTLE_INHERITED_PROPS_TRACKER.  If that part is present in a control its contents should be added\n        to the dict entry for that control, and the part removed from the control.\n        \"\"\"\n        prop_dict: Dict[str, Any] = {}\n        cat_interface = CatalogInterface(res_cat)\n        for control in cat_interface.get_all_controls_from_dict():\n            part: com.Part = pop_item_from_list(control.parts, TRESTLE_INHERITED_PROPS_TRACKER, lambda p: p.name)\n            if part:\n                props_list: List[Dict[str, Any]] = []\n                for prop in as_list(part.props):\n                    props_list.append({'name': prop.name, 'value': prop.value})\n                for sub_part in as_list(part.parts):\n                    for prop in as_list(sub_part.props):\n                        props_list.append({'name': prop.name, 'value': prop.value, 'part_name': sub_part.title})\n                prop_dict[control.id] = props_list\n        cat_interface.update_catalog_controls()\n        clean_res_cat = cat_interface.get_catalog()\n        return clean_res_cat, prop_dict\n\n    @staticmethod\n    def get_resolved_profile_catalog_and_inherited_props(\n        trestle_root: pathlib.Path,\n        profile_path: str,\n        block_adds: bool = False,\n        block_params: bool = False,\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> Tuple[cat.Catalog, Optional[Dict[str, Any]]]:\n\"\"\"\n        Create the resolved profile catalog given a profile path along with inherited props.\n\n        Args:\n            trestle_root: root directory of the trestle workspace\n            profile_path: string path or uri of the profile being resolved\n            block_adds: prevent the application of adds in the final profile\n            block_params: prevent the application of setparams in the final profile\n            params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n            param_rep: desired way to convert params to strings\n            show_value_warnings: warn if prose references a value that has not been set\n            value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n            value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n        Returns:\n            The resolved profile catalog and a control dict of inherited props\n        \"\"\"\n        logger.debug(f'get resolved profile catalog and inherited props for {profile_path} via generated Import.')\n        import_ = prof.Import(href=str(profile_path), include_all={})\n        # The final Import has change_prose=True to force parameter substitution in the prose only at the last stage.\n        import_filter = Import(\n            trestle_root,\n            import_, [],\n            True,\n            block_adds,\n            block_params,\n            params_format,\n            param_rep,\n            None,\n            show_value_warnings,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        logger.debug('launch pipeline')\n        resolved_profile_catalog = next(import_filter.process())\n        resolved_profile_catalog, inherited_props = ProfileResolver._extract_inherited_props(resolved_profile_catalog)\n        return resolved_profile_catalog, inherited_props\n\n    @staticmethod\n    def get_resolved_profile_catalog(\n        trestle_root: pathlib.Path,\n        profile_path: str,\n        block_adds: bool = False,\n        block_params: bool = False,\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> cat.Catalog:\n\"\"\"\n        Create the resolved profile catalog given a profile path.\n\n        Args:\n            trestle_root: root directory of the trestle workspace\n            profile_path: string path or uri of the profile being resolved\n            block_adds: prevent the application of adds in the final profile\n            block_params: prevent the application of setparams in the final profile\n            params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n            param_rep: desired way to convert params to strings\n            show_value_warnings: warn if prose references a value that has not been set\n            value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n            value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n        Returns:\n            The resolved profile catalog\n        \"\"\"\n        logger.debug(f'get resolved profile catalog for {profile_path} via generated Import.')\n        resolved_profile_catalog, _ = ProfileResolver.get_resolved_profile_catalog_and_inherited_props(\n            trestle_root,\n            profile_path,\n            block_adds,\n            block_params,\n            params_format,\n            param_rep,\n            show_value_warnings,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        return resolved_profile_catalog\n
                                    "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver.get_resolved_profile_catalog","title":"get_resolved_profile_catalog(trestle_root, profile_path, block_adds=False, block_params=False, params_format=None, param_rep=<ParameterRep.LEAVE_MOUSTACHE: 0>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                    Create the resolved profile catalog given a profile path.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    root directory of the trestle workspace

                                    required profile_path str

                                    string path or uri of the profile being resolved

                                    required block_adds bool

                                    prevent the application of adds in the final profile

                                    False block_params bool

                                    prevent the application of setparams in the final profile

                                    False params_format Optional[str]

                                    optional pattern with dot to wrap the param string, where dot represents the param string

                                    None param_rep ParameterRep

                                    desired way to convert params to strings

                                    <ParameterRep.LEAVE_MOUSTACHE: 0> show_value_warnings bool

                                    warn if prose references a value that has not been set

                                    False value_assigned_prefix Optional[str]

                                    Prefix placed in front of param string if a value was assigned

                                    None value_not_assigned_prefix Optional[str]

                                    Prefix placed in front of param string if a value was not assigned

                                    None

                                    Returns:

                                    Type Description Catalog

                                    The resolved profile catalog

                                    Source code in trestle/core/profile_resolver.py
                                    @staticmethod\ndef get_resolved_profile_catalog(\n    trestle_root: pathlib.Path,\n    profile_path: str,\n    block_adds: bool = False,\n    block_params: bool = False,\n    params_format: Optional[str] = None,\n    param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> cat.Catalog:\n\"\"\"\n    Create the resolved profile catalog given a profile path.\n\n    Args:\n        trestle_root: root directory of the trestle workspace\n        profile_path: string path or uri of the profile being resolved\n        block_adds: prevent the application of adds in the final profile\n        block_params: prevent the application of setparams in the final profile\n        params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n        param_rep: desired way to convert params to strings\n        show_value_warnings: warn if prose references a value that has not been set\n        value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n        value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n    Returns:\n        The resolved profile catalog\n    \"\"\"\n    logger.debug(f'get resolved profile catalog for {profile_path} via generated Import.')\n    resolved_profile_catalog, _ = ProfileResolver.get_resolved_profile_catalog_and_inherited_props(\n        trestle_root,\n        profile_path,\n        block_adds,\n        block_params,\n        params_format,\n        param_rep,\n        show_value_warnings,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    return resolved_profile_catalog\n
                                    "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver.get_resolved_profile_catalog_and_inherited_props","title":"get_resolved_profile_catalog_and_inherited_props(trestle_root, profile_path, block_adds=False, block_params=False, params_format=None, param_rep=<ParameterRep.LEAVE_MOUSTACHE: 0>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                    Create the resolved profile catalog given a profile path along with inherited props.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    root directory of the trestle workspace

                                    required profile_path str

                                    string path or uri of the profile being resolved

                                    required block_adds bool

                                    prevent the application of adds in the final profile

                                    False block_params bool

                                    prevent the application of setparams in the final profile

                                    False params_format Optional[str]

                                    optional pattern with dot to wrap the param string, where dot represents the param string

                                    None param_rep ParameterRep

                                    desired way to convert params to strings

                                    <ParameterRep.LEAVE_MOUSTACHE: 0> show_value_warnings bool

                                    warn if prose references a value that has not been set

                                    False value_assigned_prefix Optional[str]

                                    Prefix placed in front of param string if a value was assigned

                                    None value_not_assigned_prefix Optional[str]

                                    Prefix placed in front of param string if a value was not assigned

                                    None

                                    Returns:

                                    Type Description Tuple[trestle.oscal.catalog.Catalog, Optional[Dict[str, Any]]]

                                    The resolved profile catalog and a control dict of inherited props

                                    Source code in trestle/core/profile_resolver.py
                                    @staticmethod\ndef get_resolved_profile_catalog_and_inherited_props(\n    trestle_root: pathlib.Path,\n    profile_path: str,\n    block_adds: bool = False,\n    block_params: bool = False,\n    params_format: Optional[str] = None,\n    param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> Tuple[cat.Catalog, Optional[Dict[str, Any]]]:\n\"\"\"\n    Create the resolved profile catalog given a profile path along with inherited props.\n\n    Args:\n        trestle_root: root directory of the trestle workspace\n        profile_path: string path or uri of the profile being resolved\n        block_adds: prevent the application of adds in the final profile\n        block_params: prevent the application of setparams in the final profile\n        params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n        param_rep: desired way to convert params to strings\n        show_value_warnings: warn if prose references a value that has not been set\n        value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n        value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n    Returns:\n        The resolved profile catalog and a control dict of inherited props\n    \"\"\"\n    logger.debug(f'get resolved profile catalog and inherited props for {profile_path} via generated Import.')\n    import_ = prof.Import(href=str(profile_path), include_all={})\n    # The final Import has change_prose=True to force parameter substitution in the prose only at the last stage.\n    import_filter = Import(\n        trestle_root,\n        import_, [],\n        True,\n        block_adds,\n        block_params,\n        params_format,\n        param_rep,\n        None,\n        show_value_warnings,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    logger.debug('launch pipeline')\n    resolved_profile_catalog = next(import_filter.process())\n    resolved_profile_catalog, inherited_props = ProfileResolver._extract_inherited_props(resolved_profile_catalog)\n    return resolved_profile_catalog, inherited_props\n
                                    "},{"location":"api_reference/trestle.core.refs_validator/","title":"refs_validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator","title":"trestle.core.refs_validator","text":"

                                    Validate by confirming all refs have corresponding id.

                                    "},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator.RefsValidator","title":" RefsValidator (Validator) ","text":"

                                    Validator to confirm all references in responsible parties are found in roles.

                                    Source code in trestle/core/refs_validator.py
                                    class RefsValidator(Validator):\n\"\"\"Validator to confirm all references in responsible parties are found in roles.\"\"\"\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if the model's responsible parties match those found in roles.\n        \"\"\"\n        roles = as_list(model.metadata.roles)\n        role_ids = [role.id for role in roles]\n        responsible_parties = as_list(model.metadata.responsible_parties)\n        if not responsible_parties:\n            return True\n        party_roles = [party.role_id for party in responsible_parties]\n        # return true if all party roles are in the roles list\n        return all(item in role_ids for item in party_roles)\n
                                    "},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator.RefsValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator.RefsValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                    Test if the model is valid.

                                    Parameters:

                                    Name Type Description Default model ~TopLevelOscalModel

                                    A top level OSCAL model.

                                    required quiet bool

                                    Don't report msgs unless invalid.

                                    required

                                    Returns:

                                    Type Description bool

                                    True (valid) if the model's responsible parties match those found in roles.

                                    Source code in trestle/core/refs_validator.py
                                    def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if the model's responsible parties match those found in roles.\n    \"\"\"\n    roles = as_list(model.metadata.roles)\n    role_ids = [role.id for role in roles]\n    responsible_parties = as_list(model.metadata.responsible_parties)\n    if not responsible_parties:\n        return True\n    party_roles = [party.role_id for party in responsible_parties]\n    # return true if all party roles are in the roles list\n    return all(item in role_ids for item in party_roles)\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/","title":"cache","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache","title":"trestle.core.remote.cache","text":"

                                    Trestle cache operations library.

                                    Allows for using URI's to reference external directories and then expand.

                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase","title":" FetcherBase (ABC) ","text":"

                                    FetcherBase - base class for caching and fetching remote oscal objects.

                                    Source code in trestle/core/remote/cache.py
                                    class FetcherBase(ABC):\n\"\"\"FetcherBase - base class for caching and fetching remote oscal objects.\"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Intialize fetcher base.\n\n        Args:\n            trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n            uri: Reference to the source object to cache.\n        \"\"\"\n        logger.debug('Initializing FetcherBase')\n        self._cached_object_path: pathlib.Path\n        self._uri = uri\n        self._trestle_root = trestle_root.resolve()\n        self._trestle_cache_path: pathlib.Path = self._trestle_root / const.TRESTLE_CACHE_DIR\n        # ensure trestle cache directory exists.\n        self._trestle_cache_path.mkdir(exist_ok=True)\n        self._expiration_seconds = const.DAY_SECONDS\n\n    @staticmethod\n    def _time_since_modification(file_path: pathlib.Path) -> datetime.timedelta:\n\"\"\"Get time since last modification.\"\"\"\n        last_modification = datetime.datetime.fromtimestamp(file_path.stat().st_mtime)\n        return datetime.datetime.now() - last_modification\n\n    @abstractmethod\n    def _do_fetch(self) -> None:\n\"\"\"Fetch the object from a remote source.\"\"\"\n        pass\n\n    def _in_cache(self) -> bool:\n\"\"\"Return whether object is present in the cache or not.\"\"\"\n        return self._cached_object_path.exists()\n\n    def _is_stale(self) -> bool:\n        # Either cache empty or cached item is too old\n        if not self._in_cache():\n            return True\n        return FetcherBase._time_since_modification(self._cached_object_path\n                                                    ) > datetime.timedelta(seconds=self._expiration_seconds)\n\n    def _update_cache(self, force_update: bool = False) -> bool:\n\"\"\"Update the cache by fetching the target remote object, if stale or forced.\n\n        Args:\n            force_update: force the fetch regardless of staleness.\n\n        Returns:\n            True if update occurred\n        \"\"\"\n        if self._is_stale() or force_update:\n            try:\n                self._do_fetch()\n                return True\n            except Exception as e:\n                raise TrestleError(\n                    f'Cache update failure for {self._uri}.  Please confirm the file is json and not html: {e}.'\n                ) from e  # noqa E501\n        return False\n\n    def get_raw(self, force_update: bool = False) -> Dict[str, Any]:\n\"\"\"Retrieve the raw dictionary representing the underlying object.\"\"\"\n        self._update_cache(force_update)\n        # Return results in the cache, whether yaml or json, or whatever is supported by fs.load_file().\n        try:\n            raw_data = file_utils.load_file(self._cached_object_path)\n        except Exception:\n            try:\n                raw_data = file_utils.load_file(self._cached_object_path)\n            except Exception as e:\n                raise TrestleError(f'Cache get failure for {self._uri}: {e}.') from e\n        return raw_data\n\n    def get_oscal_with_model_type(self,\n                                  model_type: Type[OscalBaseModel],\n                                  force_update: bool = False) -> Optional[OscalBaseModel]:\n\"\"\"Retrieve the cached file as a particular OSCAL model.\n\n        Arguments:\n            model_type: Type[OscalBaseModel] Specifies the OSCAL model type of the fetched object.\n        \"\"\"\n        self._update_cache(force_update)\n        cache_file = self._cached_object_path\n        if not cache_file.exists():\n            raise TrestleError(f'get_oscal failure for {self._uri}')\n\n        try:\n            return model_type.oscal_read(cache_file)\n        except Exception as e:\n            logger.debug(f'get_oscal failed, error loading cache file for {self._uri} as {model_type}')\n            raise TrestleError(f'get_oscal failure for {self._uri}: {e}.') from e\n\n    def get_oscal(self, force_update: bool = False) -> Tuple[OscalBaseModel, str]:\n\"\"\"Retrieve the cached file and model name without knowing its model type.\"\"\"\n        model_dict = self.get_raw(force_update)\n        root_key = parser.root_key(model_dict)\n        model_name = parser.to_full_model_name(root_key)\n        if model_name is None:\n            raise TrestleError(f'Failed cache read of non top level model with root_key {root_key}')\n        return parser.parse_dict(model_dict[root_key], model_name), root_key\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                    Intialize fetcher base.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    Path of the trestle workspace, i.e., within which .trestle is to be found.

                                    required uri str

                                    Reference to the source object to cache.

                                    required Source code in trestle/core/remote/cache.py
                                    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Intialize fetcher base.\n\n    Args:\n        trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n        uri: Reference to the source object to cache.\n    \"\"\"\n    logger.debug('Initializing FetcherBase')\n    self._cached_object_path: pathlib.Path\n    self._uri = uri\n    self._trestle_root = trestle_root.resolve()\n    self._trestle_cache_path: pathlib.Path = self._trestle_root / const.TRESTLE_CACHE_DIR\n    # ensure trestle cache directory exists.\n    self._trestle_cache_path.mkdir(exist_ok=True)\n    self._expiration_seconds = const.DAY_SECONDS\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.get_oscal","title":"get_oscal(self, force_update=False)","text":"

                                    Retrieve the cached file and model name without knowing its model type.

                                    Source code in trestle/core/remote/cache.py
                                    def get_oscal(self, force_update: bool = False) -> Tuple[OscalBaseModel, str]:\n\"\"\"Retrieve the cached file and model name without knowing its model type.\"\"\"\n    model_dict = self.get_raw(force_update)\n    root_key = parser.root_key(model_dict)\n    model_name = parser.to_full_model_name(root_key)\n    if model_name is None:\n        raise TrestleError(f'Failed cache read of non top level model with root_key {root_key}')\n    return parser.parse_dict(model_dict[root_key], model_name), root_key\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.get_oscal_with_model_type","title":"get_oscal_with_model_type(self, model_type, force_update=False)","text":"

                                    Retrieve the cached file as a particular OSCAL model.

                                    Parameters:

                                    Name Type Description Default model_type Type[trestle.core.base_model.OscalBaseModel]

                                    Type[OscalBaseModel] Specifies the OSCAL model type of the fetched object.

                                    required Source code in trestle/core/remote/cache.py
                                    def get_oscal_with_model_type(self,\n                              model_type: Type[OscalBaseModel],\n                              force_update: bool = False) -> Optional[OscalBaseModel]:\n\"\"\"Retrieve the cached file as a particular OSCAL model.\n\n    Arguments:\n        model_type: Type[OscalBaseModel] Specifies the OSCAL model type of the fetched object.\n    \"\"\"\n    self._update_cache(force_update)\n    cache_file = self._cached_object_path\n    if not cache_file.exists():\n        raise TrestleError(f'get_oscal failure for {self._uri}')\n\n    try:\n        return model_type.oscal_read(cache_file)\n    except Exception as e:\n        logger.debug(f'get_oscal failed, error loading cache file for {self._uri} as {model_type}')\n        raise TrestleError(f'get_oscal failure for {self._uri}: {e}.') from e\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.get_raw","title":"get_raw(self, force_update=False)","text":"

                                    Retrieve the raw dictionary representing the underlying object.

                                    Source code in trestle/core/remote/cache.py
                                    def get_raw(self, force_update: bool = False) -> Dict[str, Any]:\n\"\"\"Retrieve the raw dictionary representing the underlying object.\"\"\"\n    self._update_cache(force_update)\n    # Return results in the cache, whether yaml or json, or whatever is supported by fs.load_file().\n    try:\n        raw_data = file_utils.load_file(self._cached_object_path)\n    except Exception:\n        try:\n            raw_data = file_utils.load_file(self._cached_object_path)\n        except Exception as e:\n            raise TrestleError(f'Cache get failure for {self._uri}: {e}.') from e\n    return raw_data\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory","title":" FetcherFactory ","text":"

                                    Factory method for creating a fetcher.

                                    Source code in trestle/core/remote/cache.py
                                    class FetcherFactory:\n\"\"\"Factory method for creating a fetcher.\"\"\"\n\n    class UriType(Enum):\n\"\"\"Specify types of URI.\"\"\"\n\n        LOCAL_FILE = 1\n\n        SFTP = 2\n\n        HTTPS = 3\n\n        TRESTLE = 4\n\n    @staticmethod\n    def uri_type_is_not_local(uri_type: UriType) -> bool:\n\"\"\"Determine if the uri type is not local.\"\"\"\n        return uri_type in [FetcherFactory.UriType.SFTP, FetcherFactory.UriType.HTTPS]\n\n    @staticmethod\n    def get_uri_type(uri: str) -> UriType:\n\"\"\"Determine the type of uri.\"\"\"\n        if uri.startswith(const.SFTP_URI):\n            return FetcherFactory.UriType.SFTP\n        if uri.startswith(const.HTTPS_URI):\n            return FetcherFactory.UriType.HTTPS\n        if uri.startswith(const.TRESTLE_HREF_HEADING):\n            return FetcherFactory.UriType.TRESTLE\n        # if we land here, assume it is a local file and may have relative path\n        # but it at least needs a filename with suffix\n        # the most minimal allowed uri is of the form a.yml\n        uri_clean = uri.strip()\n        if uri_clean.startswith('ftp:'):\n            raise TrestleError(f'Invalid uri {uri}  ftp is not supported.  Use sftp instead.')\n        uri_len = len(uri_clean)\n        # at least 5 chars and ending with dot followed by at least 3 chars\n        if uri_len > 4 and 0 < uri_clean.rfind('.') < uri_len - 3:\n            return FetcherFactory.UriType.LOCAL_FILE\n        raise TrestleError(f'Invalid uri not recognized as a readable file path with extension: {uri}')\n\n    @staticmethod\n    def in_trestle_directory(trestle_root: pathlib.Path, uri: str) -> bool:\n\"\"\"Check if in trestle directory when uri may not be a file path.\"\"\"\n        uri_type = FetcherFactory.get_uri_type(uri)\n        if uri_type == FetcherFactory.UriType.TRESTLE:\n            return True\n        if uri_type != FetcherFactory.UriType.LOCAL_FILE:\n            return False\n        try:\n            pathlib.Path(uri).resolve().relative_to(str(trestle_root.resolve()))\n        except Exception:\n            return False\n        return True\n\n    @classmethod\n    def get_fetcher(cls, trestle_root: pathlib.Path, uri: str) -> Union[LocalFetcher, SFTPFetcher, HTTPSFetcher]:\n\"\"\"Return an instantiated fetcher object based on the type of URI.\n\n        Args:\n            trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n            uri: Reference to the remote object to cache.\n\n        Returns:\n            fetcher object for the given URI.\n        \"\"\"\n        fetcher_dict = {\n            FetcherFactory.UriType.LOCAL_FILE: LocalFetcher,\n            FetcherFactory.UriType.SFTP: SFTPFetcher,\n            FetcherFactory.UriType.HTTPS: HTTPSFetcher,\n            FetcherFactory.UriType.TRESTLE: LocalFetcher,\n        }\n        uri_type = cls.get_uri_type(uri)\n        return fetcher_dict[uri_type](trestle_root, uri)  # type: ignore\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.UriType","title":" UriType (Enum) ","text":"

                                    Specify types of URI.

                                    Source code in trestle/core/remote/cache.py
                                    class UriType(Enum):\n\"\"\"Specify types of URI.\"\"\"\n\n    LOCAL_FILE = 1\n\n    SFTP = 2\n\n    HTTPS = 3\n\n    TRESTLE = 4\n
                                    HTTPS \u00a4 LOCAL_FILE \u00a4 SFTP \u00a4 TRESTLE \u00a4"},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.get_fetcher","title":"get_fetcher(trestle_root, uri) classmethod","text":"

                                    Return an instantiated fetcher object based on the type of URI.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    Path of the trestle workspace, i.e., within which .trestle is to be found.

                                    required uri str

                                    Reference to the remote object to cache.

                                    required

                                    Returns:

                                    Type Description Union[trestle.core.remote.cache.LocalFetcher, trestle.core.remote.cache.SFTPFetcher, trestle.core.remote.cache.HTTPSFetcher]

                                    fetcher object for the given URI.

                                    Source code in trestle/core/remote/cache.py
                                    @classmethod\ndef get_fetcher(cls, trestle_root: pathlib.Path, uri: str) -> Union[LocalFetcher, SFTPFetcher, HTTPSFetcher]:\n\"\"\"Return an instantiated fetcher object based on the type of URI.\n\n    Args:\n        trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n        uri: Reference to the remote object to cache.\n\n    Returns:\n        fetcher object for the given URI.\n    \"\"\"\n    fetcher_dict = {\n        FetcherFactory.UriType.LOCAL_FILE: LocalFetcher,\n        FetcherFactory.UriType.SFTP: SFTPFetcher,\n        FetcherFactory.UriType.HTTPS: HTTPSFetcher,\n        FetcherFactory.UriType.TRESTLE: LocalFetcher,\n    }\n    uri_type = cls.get_uri_type(uri)\n    return fetcher_dict[uri_type](trestle_root, uri)  # type: ignore\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.get_uri_type","title":"get_uri_type(uri) staticmethod","text":"

                                    Determine the type of uri.

                                    Source code in trestle/core/remote/cache.py
                                    @staticmethod\ndef get_uri_type(uri: str) -> UriType:\n\"\"\"Determine the type of uri.\"\"\"\n    if uri.startswith(const.SFTP_URI):\n        return FetcherFactory.UriType.SFTP\n    if uri.startswith(const.HTTPS_URI):\n        return FetcherFactory.UriType.HTTPS\n    if uri.startswith(const.TRESTLE_HREF_HEADING):\n        return FetcherFactory.UriType.TRESTLE\n    # if we land here, assume it is a local file and may have relative path\n    # but it at least needs a filename with suffix\n    # the most minimal allowed uri is of the form a.yml\n    uri_clean = uri.strip()\n    if uri_clean.startswith('ftp:'):\n        raise TrestleError(f'Invalid uri {uri}  ftp is not supported.  Use sftp instead.')\n    uri_len = len(uri_clean)\n    # at least 5 chars and ending with dot followed by at least 3 chars\n    if uri_len > 4 and 0 < uri_clean.rfind('.') < uri_len - 3:\n        return FetcherFactory.UriType.LOCAL_FILE\n    raise TrestleError(f'Invalid uri not recognized as a readable file path with extension: {uri}')\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.in_trestle_directory","title":"in_trestle_directory(trestle_root, uri) staticmethod","text":"

                                    Check if in trestle directory when uri may not be a file path.

                                    Source code in trestle/core/remote/cache.py
                                    @staticmethod\ndef in_trestle_directory(trestle_root: pathlib.Path, uri: str) -> bool:\n\"\"\"Check if in trestle directory when uri may not be a file path.\"\"\"\n    uri_type = FetcherFactory.get_uri_type(uri)\n    if uri_type == FetcherFactory.UriType.TRESTLE:\n        return True\n    if uri_type != FetcherFactory.UriType.LOCAL_FILE:\n        return False\n    try:\n        pathlib.Path(uri).resolve().relative_to(str(trestle_root.resolve()))\n    except Exception:\n        return False\n    return True\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.uri_type_is_not_local","title":"uri_type_is_not_local(uri_type) staticmethod","text":"

                                    Determine if the uri type is not local.

                                    Source code in trestle/core/remote/cache.py
                                    @staticmethod\ndef uri_type_is_not_local(uri_type: UriType) -> bool:\n\"\"\"Determine if the uri type is not local.\"\"\"\n    return uri_type in [FetcherFactory.UriType.SFTP, FetcherFactory.UriType.HTTPS]\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.HTTPSFetcher","title":" HTTPSFetcher (FetcherBase) ","text":"

                                    Fetcher for https content.

                                    Source code in trestle/core/remote/cache.py
                                    class HTTPSFetcher(FetcherBase):\n\"\"\"Fetcher for https content.\"\"\"\n\n    # Use request: https://requests.readthedocs.io/en/master/\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize HTTPS fetcher.\"\"\"\n        logger.debug('Initializing HTTPSFetcher')\n        super().__init__(trestle_root, uri)\n        self._username = None\n        self._password = None\n        u = parse.urlparse(self._uri)\n        self._url = uri\n        # If the either the username or password is omitted in the URI, then the other becomes ''\n        # so we test for either None or ''.\n        if u.username != '' and u.username is not None:\n            # This also checks for invalid environment variable name (IEEE 1003.1)\n            if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.username) or u.username == '{{_}}':\n                raise TrestleError(\n                    'Cache request for invalid input URI: '\n                    f'username must refer to an environment variable using moustache {self._uri}'\n                )\n            username_var = u.username[2:-2]\n            if username_var not in os.environ:\n                raise TrestleError(\n                    f'Cache request for invalid input URI: username not found in the environment {self._uri}'\n                )\n            self._username = os.environ[username_var]\n        if u.password != '' and u.password is not None:  # noqa S105\n            if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.password) or u.password == '{{_}}':  # noqa S105\n                raise TrestleError(\n                    'Cache request for invalid input URI: '\n                    f'password must refer to an environment variable using moustache {self._uri}'\n                )\n            password_var = u.password[2:-2]\n            if password_var not in os.environ:\n                raise TrestleError(\n                    'Cache request for invalid input URI: '\n                    f'password not found in the environment {self._uri}'\n                )\n            self._password = os.environ[password_var]\n        if self._username and (self._password == '' or self._password is None):  # noqa S105\n            raise TrestleError(\n                f'Cache request for invalid input URI: username found '\n                f'but password not found via environment variable {self._uri}'\n            )\n        if self._password and not self._username:\n            raise TrestleError(\n                f'Cache request for invalid input URI: password found '\n                f'but username not found via environment variable {self._uri}'\n            )\n        if u.hostname is None:\n            raise TrestleError(f'Cache request for {self._uri} requires hostname')\n        https_cached_dir = self._trestle_cache_path / u.hostname\n        # Skip any number of back- or forward slashes preceding the URI path (u.path)\n        path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n        https_cached_dir = https_cached_dir / path_parent\n        https_cached_dir.mkdir(parents=True, exist_ok=True)\n        self._cached_object_path = https_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n\n    def _do_fetch(self) -> None:\n        auth = None\n        verify = None\n        # This order reflects requests library behavior: REQUESTS_CA_BUNDLE comes first.\n        for env_var_name in ['REQUESTS_CA_BUNDLE', 'CURL_CA_BUNDLE']:\n            if env_var_name in os.environ:\n                if pathlib.Path(os.environ[env_var_name]).exists():\n                    verify = os.environ[env_var_name]\n                    break\n                else:\n                    err_str = f'Env var ${env_var_name} found but path does not exist: {os.environ[env_var_name]}'\n                    logger.warning(err_str)\n                    raise TrestleError(f'Cache update failure with bad inputenv var: {err_str}')\n        if self._username is not None and self._password is not None:\n            auth = HTTPBasicAuth(self._username, self._password)\n\n        try:\n            response = requests.get(self._url, auth=auth, verify=verify, timeout=30)\n        except Exception as e:\n            raise TrestleError(f'Cache update failure to connect via HTTPS: {self._url} ({e})')\n\n        if response.status_code == 200:\n            try:\n                result = response.text\n            except Exception as err:\n                raise TrestleError(f'Cache update failure reading response via HTTPS: {self._url} ({err})')\n            else:\n                self._cached_object_path.write_text(result, encoding=const.FILE_ENCODING)\n        else:\n            raise TrestleError(f'GET returned code {response.status_code}: {self._uri}')\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.HTTPSFetcher-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.HTTPSFetcher.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                    Initialize HTTPS fetcher.

                                    Source code in trestle/core/remote/cache.py
                                    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize HTTPS fetcher.\"\"\"\n    logger.debug('Initializing HTTPSFetcher')\n    super().__init__(trestle_root, uri)\n    self._username = None\n    self._password = None\n    u = parse.urlparse(self._uri)\n    self._url = uri\n    # If the either the username or password is omitted in the URI, then the other becomes ''\n    # so we test for either None or ''.\n    if u.username != '' and u.username is not None:\n        # This also checks for invalid environment variable name (IEEE 1003.1)\n        if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.username) or u.username == '{{_}}':\n            raise TrestleError(\n                'Cache request for invalid input URI: '\n                f'username must refer to an environment variable using moustache {self._uri}'\n            )\n        username_var = u.username[2:-2]\n        if username_var not in os.environ:\n            raise TrestleError(\n                f'Cache request for invalid input URI: username not found in the environment {self._uri}'\n            )\n        self._username = os.environ[username_var]\n    if u.password != '' and u.password is not None:  # noqa S105\n        if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.password) or u.password == '{{_}}':  # noqa S105\n            raise TrestleError(\n                'Cache request for invalid input URI: '\n                f'password must refer to an environment variable using moustache {self._uri}'\n            )\n        password_var = u.password[2:-2]\n        if password_var not in os.environ:\n            raise TrestleError(\n                'Cache request for invalid input URI: '\n                f'password not found in the environment {self._uri}'\n            )\n        self._password = os.environ[password_var]\n    if self._username and (self._password == '' or self._password is None):  # noqa S105\n        raise TrestleError(\n            f'Cache request for invalid input URI: username found '\n            f'but password not found via environment variable {self._uri}'\n        )\n    if self._password and not self._username:\n        raise TrestleError(\n            f'Cache request for invalid input URI: password found '\n            f'but username not found via environment variable {self._uri}'\n        )\n    if u.hostname is None:\n        raise TrestleError(f'Cache request for {self._uri} requires hostname')\n    https_cached_dir = self._trestle_cache_path / u.hostname\n    # Skip any number of back- or forward slashes preceding the URI path (u.path)\n    path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n    https_cached_dir = https_cached_dir / path_parent\n    https_cached_dir.mkdir(parents=True, exist_ok=True)\n    self._cached_object_path = https_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.LocalFetcher","title":" LocalFetcher (FetcherBase) ","text":"

                                    Fetcher for local content.

                                    Used for both file:/// and C:\\ or C:/ type paths, but the path must be absolute. Also used for trestle:// files present in the current trestle root.

                                    If file:/// is used on a Windows system, it must be followed by C:/ or other drive letter to be sure it is an absolute path, e.g. file:///C:/Users/Default/Documents/profile.json. The drive letter may be lowercase. LocalFetcher does not do any caching and assumes the file is quickly accessible.

                                    Source code in trestle/core/remote/cache.py
                                    class LocalFetcher(FetcherBase):\nr\"\"\"Fetcher for local content.\n\n    Used for both file:/// and C:\\\\ or C:/ type paths, but the path must be absolute.\n    Also used for trestle:// files present in the current trestle root.\n\n    If file:/// is used on a Windows system, it must be followed by C:/ or other drive letter\n    to be sure it is an absolute path, e.g. file:///C:/Users/Default/Documents/profile.json.\n    The drive letter may be lowercase.\n    LocalFetcher does not do any caching and assumes the file is quickly accessible.\n    \"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize local fetcher.\n\n        Args:\n            trestle_root: trestle root path\n            uri: Reference to the file in the local filesystem to cache, which must be outside trestle_root.\n        \"\"\"\n        super().__init__(trestle_root, uri)\n\n        # Handle as file:/// form\n        if uri.startswith(const.FILE_URI):\n            # strip off entire header including /\n            uri = uri[len(const.FILE_URI):]\n\n            # if it has a drive letter don't add / to front\n            uri = uri if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri) else '/' + uri\n        elif uri.startswith(const.TRESTLE_HREF_HEADING):\n            uri = str(trestle_root / uri[len(const.TRESTLE_HREF_HEADING):])\n            self._abs_path = pathlib.Path(uri).resolve()\n            self._cached_object_path = self._abs_path\n            return\n\n        # now the URI should be either unix / style or windows C:/ style.  It may be relative.\n\n        if ':' in uri and platform.system() != const.WINDOWS_PLATFORM_STR:\n            raise TrestleError(f'Cannot have : in uri on non-Windows system unless ftps, https or trestle: {uri}')\n\n        # if it has a drive letter but no / after it, it is not absolute\n        if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri):\n            if platform.system() != const.WINDOWS_PLATFORM_STR:\n                raise TrestleError(f'Cannot cache Windows paths on non-Windows system. {uri}')\n\n        # store the abs path to the file for fetching\n        # if this is a windows file it will have a drive letter at start after resolve\n        try:\n            self._abs_path = pathlib.Path(uri).resolve()\n        except Exception:\n            raise TrestleError(f'The uri provided is invalid or unresolvable as a file path: {uri}')\n\n        # set the cached path to be the actual file path\n        self._cached_object_path = self._abs_path\n\n    def _is_stale(self) -> bool:\n        # Local file is always stale.\n        return True\n\n    def _do_fetch(self) -> None:\n\"\"\"No need to fetch since using actual file path.\"\"\"\n        pass\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.LocalFetcher-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.LocalFetcher.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                    Initialize local fetcher.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    trestle root path

                                    required uri str

                                    Reference to the file in the local filesystem to cache, which must be outside trestle_root.

                                    required Source code in trestle/core/remote/cache.py
                                    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize local fetcher.\n\n    Args:\n        trestle_root: trestle root path\n        uri: Reference to the file in the local filesystem to cache, which must be outside trestle_root.\n    \"\"\"\n    super().__init__(trestle_root, uri)\n\n    # Handle as file:/// form\n    if uri.startswith(const.FILE_URI):\n        # strip off entire header including /\n        uri = uri[len(const.FILE_URI):]\n\n        # if it has a drive letter don't add / to front\n        uri = uri if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri) else '/' + uri\n    elif uri.startswith(const.TRESTLE_HREF_HEADING):\n        uri = str(trestle_root / uri[len(const.TRESTLE_HREF_HEADING):])\n        self._abs_path = pathlib.Path(uri).resolve()\n        self._cached_object_path = self._abs_path\n        return\n\n    # now the URI should be either unix / style or windows C:/ style.  It may be relative.\n\n    if ':' in uri and platform.system() != const.WINDOWS_PLATFORM_STR:\n        raise TrestleError(f'Cannot have : in uri on non-Windows system unless ftps, https or trestle: {uri}')\n\n    # if it has a drive letter but no / after it, it is not absolute\n    if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri):\n        if platform.system() != const.WINDOWS_PLATFORM_STR:\n            raise TrestleError(f'Cannot cache Windows paths on non-Windows system. {uri}')\n\n    # store the abs path to the file for fetching\n    # if this is a windows file it will have a drive letter at start after resolve\n    try:\n        self._abs_path = pathlib.Path(uri).resolve()\n    except Exception:\n        raise TrestleError(f'The uri provided is invalid or unresolvable as a file path: {uri}')\n\n    # set the cached path to be the actual file path\n    self._cached_object_path = self._abs_path\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.SFTPFetcher","title":" SFTPFetcher (FetcherBase) ","text":"

                                    Fetcher for SFTP content.

                                    Source code in trestle/core/remote/cache.py
                                    class SFTPFetcher(FetcherBase):\n\"\"\"Fetcher for SFTP content.\"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize SFTP fetcher. Update the expected cache path as per caching specs.\n\n        Args:\n            trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n            uri: Reference to the remote file to cache that can be fetched using the sftp:// scheme.\n        \"\"\"\n        logger.debug(f'initialize SFTPFetcher for uri {uri}')\n        super().__init__(trestle_root, uri)\n        # Is this a valid URI, however? Username and password are optional, of course.\n        try:\n            u = parse.urlparse(self._uri)\n        except Exception as e:\n            logger.warning(f'SFTP fetcher unable to parse uri {self._uri} error {e}')\n            raise TrestleError(f'Unable to parse malformed url {self._uri} error {e}')\n        logger.debug(f'SFTP fetcher with parsed uri {u}')\n        if not u.hostname:\n            logger.debug('SFTP fetcher uri missing hostname')\n            logger.warning(f'Malformed URI, cannot parse hostname in URL {self._uri}')\n            raise TrestleError(f'Cache request for invalid input URI: missing hostname {self._uri}')\n        if not u.path:\n            logger.debug('SFTP fetcher uri missing path')\n            logger.warning(f'Malformed URI, cannot parse path in URL {self._uri}')\n            raise TrestleError(f'Cache request for invalid input URI: missing file path {self._uri}')\n\n        sftp_cached_dir = self._trestle_cache_path / u.hostname\n        # Skip any number of back- or forward slashes preceding the URL path (u.path)\n        path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n        sftp_cached_dir = sftp_cached_dir / path_parent\n        sftp_cached_dir.mkdir(parents=True, exist_ok=True)\n        self._cached_object_path = sftp_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n\n    def _do_fetch(self) -> None:\n\"\"\"Fetch remote object and update the cache if appropriate and possible to do so.\n\n        Authentication relies on the user's private key being either active via ssh-agent or\n        supplied via environment variable SSH_KEY. In the latter case, it must not require a passphrase prompt.\n        \"\"\"\n        u = parse.urlparse(self._uri)\n        client = paramiko.SSHClient()\n        # Must pick up host keys from the default known_hosts on this environment:\n        try:\n            client.load_system_host_keys()\n        except Exception as e:\n            raise TrestleError(f'Cache update failure for {self._uri}: {e}.')\n        # Use the supplied private key file if given, or look for keys in default path.\n        if 'SSH_KEY' in os.environ:\n            pkey = paramiko.RSAKey.from_private_key(StringIO(os.environ['SSH_KEY']))\n            look_for_keys = False\n        else:\n            pkey = None\n            look_for_keys = True\n\n        username = getpass.getuser() if not u.username else u.username\n        try:\n            client.connect(\n                u.hostname,\n                username=username,\n                password=u.password,\n                pkey=pkey,\n                look_for_keys=look_for_keys,\n                port=22 if not u.port else u.port,\n            )\n        except Exception as e:\n            raise TrestleError(f'Cache update failure to connect via SSH: {u.hostname}: {e}.')\n\n        try:\n            sftp_client = client.open_sftp()\n        except Exception as e:\n            raise TrestleError(f'Cache update failure to open sftp for {u.hostname}: {e}.')\n\n        localpath = self._cached_object_path\n        try:\n            sftp_client.get(remotepath=u.path[1:], localpath=(localpath.__str__()))\n        except Exception as e:\n            raise TrestleError(f'Error getting remote resource {self._uri} into cache {localpath}: {e}')\n
                                    "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.SFTPFetcher-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.SFTPFetcher.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                    Initialize SFTP fetcher. Update the expected cache path as per caching specs.

                                    Parameters:

                                    Name Type Description Default trestle_root Path

                                    Path of the trestle workspace, i.e., within which .trestle is to be found.

                                    required uri str

                                    Reference to the remote file to cache that can be fetched using the sftp:// scheme.

                                    required Source code in trestle/core/remote/cache.py
                                    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize SFTP fetcher. Update the expected cache path as per caching specs.\n\n    Args:\n        trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n        uri: Reference to the remote file to cache that can be fetched using the sftp:// scheme.\n    \"\"\"\n    logger.debug(f'initialize SFTPFetcher for uri {uri}')\n    super().__init__(trestle_root, uri)\n    # Is this a valid URI, however? Username and password are optional, of course.\n    try:\n        u = parse.urlparse(self._uri)\n    except Exception as e:\n        logger.warning(f'SFTP fetcher unable to parse uri {self._uri} error {e}')\n        raise TrestleError(f'Unable to parse malformed url {self._uri} error {e}')\n    logger.debug(f'SFTP fetcher with parsed uri {u}')\n    if not u.hostname:\n        logger.debug('SFTP fetcher uri missing hostname')\n        logger.warning(f'Malformed URI, cannot parse hostname in URL {self._uri}')\n        raise TrestleError(f'Cache request for invalid input URI: missing hostname {self._uri}')\n    if not u.path:\n        logger.debug('SFTP fetcher uri missing path')\n        logger.warning(f'Malformed URI, cannot parse path in URL {self._uri}')\n        raise TrestleError(f'Cache request for invalid input URI: missing file path {self._uri}')\n\n    sftp_cached_dir = self._trestle_cache_path / u.hostname\n    # Skip any number of back- or forward slashes preceding the URL path (u.path)\n    path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n    sftp_cached_dir = sftp_cached_dir / path_parent\n    sftp_cached_dir.mkdir(parents=True, exist_ok=True)\n    self._cached_object_path = sftp_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n
                                    "},{"location":"api_reference/trestle.core.repository/","title":"repository","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository","title":"trestle.core.repository","text":"

                                    Trestle Repository APIs.

                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring","title":" AgileAuthoring (Repository) ","text":"

                                    AgileAuthoring extends the Repository class for performing authoring specific operations on Trestle repository.

                                    This class provides a set of APIs to perform generate and assemble authoring operations in the trestle repository rather than using the command line.

                                    Source code in trestle/core/repository.py
                                    class AgileAuthoring(Repository):\n\"\"\"\n    AgileAuthoring extends the Repository class for performing authoring specific operations on Trestle repository.\n\n    This class provides a set of APIs to perform generate and assemble authoring operations in the trestle repository\n    rather than using the command line.\n\n    \"\"\"\n\n    def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n        super().__init__(root_dir)\n\n    def assemble_catalog_markdown(\n        self,\n        name: str,\n        output: str,\n        markdown_dir: str,\n        set_parameters: bool = False,\n        regenerate: bool = False,\n        version: str = ''\n    ) -> bool:\n\"\"\"Assemble catalog markdown into OSCAL Catalog in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type catalog.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            trestle_root=self.root_dir,\n            set_parameters=set_parameters,\n            regenerate=regenerate,\n            version=version,\n            verbose=verbose\n        )\n\n        try:\n            ret = catalogauthorcmd.CatalogAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling catalog {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def assemble_profile_markdown(\n        self,\n        name: str,\n        output: str,\n        markdown_dir: str,\n        set_parameters: bool = False,\n        regenerate: bool = False,\n        version: str = '',\n        sections: str = '',\n        required_sections: str = '',\n        allowed_sections: str = ''\n    ) -> bool:\n\"\"\"Assemble profile markdown into OSCAL Profile in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type profile.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            trestle_root=self.root_dir,\n            set_parameters=set_parameters,\n            regenerate=regenerate,\n            version=version,\n            sections=sections,\n            required_sections=required_sections,\n            allowed_sections=allowed_sections,\n            verbose=verbose\n        )\n\n        try:\n            ret = profileauthorcmd.ProfileAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling profile {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def assemble_component_definition_markdown(\n        self, name: str, output: str, markdown_dir: str, regenerate: bool = False, version: str = ''\n    ) -> bool:\n\"\"\"Assemble component definition markdown into OSCAL Component Definition in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type component definition.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            trestle_root=self.root_dir,\n            regenerate=regenerate,\n            version=version,\n            verbose=verbose\n        )\n\n        try:\n            ret = componentauthorcmd.ComponentAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling component definition {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def assemble_ssp_markdown(\n        self,\n        name: str,\n        output: str,\n        markdown_dir: str,\n        compdefs: str,\n        regenerate: bool = False,\n        version: str = ''\n    ) -> bool:\n\"\"\"Assemble ssp markdown into OSCAL SSP in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type ssp.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            compdefs=compdefs,\n            trestle_root=self.root_dir,\n            regenerate=regenerate,\n            version=version,\n            verbose=verbose\n        )\n\n        try:\n            ret = sspauthorcmd.SSPAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling ssp {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def generate_catalog_markdown(\n        self,\n        name: str,\n        output: str,\n        force_overwrite: bool = False,\n        yaml_header: str = '',\n        overwrite_header_values: bool = False\n    ) -> bool:\n\"\"\"Generate catalog markdown from OSCAL Catalog in JSON.\"\"\"\n        logger.debug(f'Generating markdown for {name} of type catalog.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            trestle_root=self.root_dir,\n            force_overwrite=force_overwrite,\n            yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            verbose=verbose\n        )\n\n        try:\n            ret = catalogauthorcmd.CatalogGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error generate markdown for catalog {name}: {e}')\n\n        logger.debug(f'Model {name} markdown generated successfully.')\n        return success\n\n    def generate_profile_markdown(\n        self,\n        name: str,\n        output: str,\n        force_overwrite: bool = False,\n        yaml_header: str = '',\n        overwrite_header_values: bool = False,\n        sections: str = '',\n        required_sections: str = ''\n    ) -> bool:\n\"\"\"Generate profile markdown from OSCAL Profile in JSON.\"\"\"\n        logger.debug(f'Generating markdown for {name} of type profile.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            trestle_root=self.root_dir,\n            force_overwrite=force_overwrite,\n            yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            sections=sections,\n            required_sections=required_sections,\n            verbose=verbose\n        )\n\n        try:\n            ret = profileauthorcmd.ProfileGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error generate markdown for profile {name}: {e}')\n\n        logger.debug(f'Model {name} markdown generated successfully.')\n        return success\n\n    def generate_component_definition_markdown(\n        self,\n        name: str,\n        output: str,\n        force_overwrite: bool = False,\n    ) -> bool:\n\"\"\"Generate component definition markdown from OSCAL Component Definition in JSON.\"\"\"\n        logger.debug(f'Generating markdown for {name} of type component definition.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name, output=output, trestle_root=self.root_dir, force_overwrite=force_overwrite, verbose=verbose\n        )\n\n        try:\n            ret = componentauthorcmd.ComponentGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error generating markdown for component definition {name}: {e}')\n\n        logger.debug(f'Model {name} markdown generated successfully.')\n        return success\n\n    def generate_ssp_markdown(\n        self,\n        profile: str,\n        output: str,\n        compdefs: str,\n        leveraged_ssp: str = '',\n        force_overwrite: bool = False,\n        yaml_header: str = '',\n        overwrite_header_values: bool = False\n    ) -> bool:\n\"\"\"Generate ssp markdown from OSCAL Profile and Component Definitions.\"\"\"\n        logger.debug(f'Generating markdown for {output} of type ssp.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            profile=profile,\n            output=output,\n            compdefs=compdefs,\n            leveraged_ssp=leveraged_ssp,\n            trestle_root=self.root_dir,\n            force_overwrite=force_overwrite,\n            yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            verbose=verbose\n        )\n\n        try:\n            ret = sspauthorcmd.SSPGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in generating markdown for ssp {output}: {e}')\n\n        logger.debug(f'Model {output} markdown generated successfully.')\n        return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.__init__","title":"__init__(self, root_dir) special","text":"Source code in trestle/core/repository.py
                                    def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n    super().__init__(root_dir)\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_catalog_markdown","title":"assemble_catalog_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version='')","text":"

                                    Assemble catalog markdown into OSCAL Catalog in JSON.

                                    Source code in trestle/core/repository.py
                                    def assemble_catalog_markdown(\n    self,\n    name: str,\n    output: str,\n    markdown_dir: str,\n    set_parameters: bool = False,\n    regenerate: bool = False,\n    version: str = ''\n) -> bool:\n\"\"\"Assemble catalog markdown into OSCAL Catalog in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type catalog.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        trestle_root=self.root_dir,\n        set_parameters=set_parameters,\n        regenerate=regenerate,\n        version=version,\n        verbose=verbose\n    )\n\n    try:\n        ret = catalogauthorcmd.CatalogAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling catalog {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_component_definition_markdown","title":"assemble_component_definition_markdown(self, name, output, markdown_dir, regenerate=False, version='')","text":"

                                    Assemble component definition markdown into OSCAL Component Definition in JSON.

                                    Source code in trestle/core/repository.py
                                    def assemble_component_definition_markdown(\n    self, name: str, output: str, markdown_dir: str, regenerate: bool = False, version: str = ''\n) -> bool:\n\"\"\"Assemble component definition markdown into OSCAL Component Definition in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type component definition.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        trestle_root=self.root_dir,\n        regenerate=regenerate,\n        version=version,\n        verbose=verbose\n    )\n\n    try:\n        ret = componentauthorcmd.ComponentAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling component definition {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_profile_markdown","title":"assemble_profile_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version='', sections='', required_sections='', allowed_sections='')","text":"

                                    Assemble profile markdown into OSCAL Profile in JSON.

                                    Source code in trestle/core/repository.py
                                    def assemble_profile_markdown(\n    self,\n    name: str,\n    output: str,\n    markdown_dir: str,\n    set_parameters: bool = False,\n    regenerate: bool = False,\n    version: str = '',\n    sections: str = '',\n    required_sections: str = '',\n    allowed_sections: str = ''\n) -> bool:\n\"\"\"Assemble profile markdown into OSCAL Profile in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type profile.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        trestle_root=self.root_dir,\n        set_parameters=set_parameters,\n        regenerate=regenerate,\n        version=version,\n        sections=sections,\n        required_sections=required_sections,\n        allowed_sections=allowed_sections,\n        verbose=verbose\n    )\n\n    try:\n        ret = profileauthorcmd.ProfileAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling profile {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_ssp_markdown","title":"assemble_ssp_markdown(self, name, output, markdown_dir, compdefs, regenerate=False, version='')","text":"

                                    Assemble ssp markdown into OSCAL SSP in JSON.

                                    Source code in trestle/core/repository.py
                                    def assemble_ssp_markdown(\n    self,\n    name: str,\n    output: str,\n    markdown_dir: str,\n    compdefs: str,\n    regenerate: bool = False,\n    version: str = ''\n) -> bool:\n\"\"\"Assemble ssp markdown into OSCAL SSP in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type ssp.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        compdefs=compdefs,\n        trestle_root=self.root_dir,\n        regenerate=regenerate,\n        version=version,\n        verbose=verbose\n    )\n\n    try:\n        ret = sspauthorcmd.SSPAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling ssp {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_catalog_markdown","title":"generate_catalog_markdown(self, name, output, force_overwrite=False, yaml_header='', overwrite_header_values=False)","text":"

                                    Generate catalog markdown from OSCAL Catalog in JSON.

                                    Source code in trestle/core/repository.py
                                    def generate_catalog_markdown(\n    self,\n    name: str,\n    output: str,\n    force_overwrite: bool = False,\n    yaml_header: str = '',\n    overwrite_header_values: bool = False\n) -> bool:\n\"\"\"Generate catalog markdown from OSCAL Catalog in JSON.\"\"\"\n    logger.debug(f'Generating markdown for {name} of type catalog.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        trestle_root=self.root_dir,\n        force_overwrite=force_overwrite,\n        yaml_header=yaml_header,\n        overwrite_header_values=overwrite_header_values,\n        verbose=verbose\n    )\n\n    try:\n        ret = catalogauthorcmd.CatalogGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error generate markdown for catalog {name}: {e}')\n\n    logger.debug(f'Model {name} markdown generated successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_component_definition_markdown","title":"generate_component_definition_markdown(self, name, output, force_overwrite=False)","text":"

                                    Generate component definition markdown from OSCAL Component Definition in JSON.

                                    Source code in trestle/core/repository.py
                                    def generate_component_definition_markdown(\n    self,\n    name: str,\n    output: str,\n    force_overwrite: bool = False,\n) -> bool:\n\"\"\"Generate component definition markdown from OSCAL Component Definition in JSON.\"\"\"\n    logger.debug(f'Generating markdown for {name} of type component definition.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name, output=output, trestle_root=self.root_dir, force_overwrite=force_overwrite, verbose=verbose\n    )\n\n    try:\n        ret = componentauthorcmd.ComponentGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error generating markdown for component definition {name}: {e}')\n\n    logger.debug(f'Model {name} markdown generated successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_profile_markdown","title":"generate_profile_markdown(self, name, output, force_overwrite=False, yaml_header='', overwrite_header_values=False, sections='', required_sections='')","text":"

                                    Generate profile markdown from OSCAL Profile in JSON.

                                    Source code in trestle/core/repository.py
                                    def generate_profile_markdown(\n    self,\n    name: str,\n    output: str,\n    force_overwrite: bool = False,\n    yaml_header: str = '',\n    overwrite_header_values: bool = False,\n    sections: str = '',\n    required_sections: str = ''\n) -> bool:\n\"\"\"Generate profile markdown from OSCAL Profile in JSON.\"\"\"\n    logger.debug(f'Generating markdown for {name} of type profile.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        trestle_root=self.root_dir,\n        force_overwrite=force_overwrite,\n        yaml_header=yaml_header,\n        overwrite_header_values=overwrite_header_values,\n        sections=sections,\n        required_sections=required_sections,\n        verbose=verbose\n    )\n\n    try:\n        ret = profileauthorcmd.ProfileGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error generate markdown for profile {name}: {e}')\n\n    logger.debug(f'Model {name} markdown generated successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_ssp_markdown","title":"generate_ssp_markdown(self, profile, output, compdefs, leveraged_ssp='', force_overwrite=False, yaml_header='', overwrite_header_values=False)","text":"

                                    Generate ssp markdown from OSCAL Profile and Component Definitions.

                                    Source code in trestle/core/repository.py
                                    def generate_ssp_markdown(\n    self,\n    profile: str,\n    output: str,\n    compdefs: str,\n    leveraged_ssp: str = '',\n    force_overwrite: bool = False,\n    yaml_header: str = '',\n    overwrite_header_values: bool = False\n) -> bool:\n\"\"\"Generate ssp markdown from OSCAL Profile and Component Definitions.\"\"\"\n    logger.debug(f'Generating markdown for {output} of type ssp.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        profile=profile,\n        output=output,\n        compdefs=compdefs,\n        leveraged_ssp=leveraged_ssp,\n        trestle_root=self.root_dir,\n        force_overwrite=force_overwrite,\n        yaml_header=yaml_header,\n        overwrite_header_values=overwrite_header_values,\n        verbose=verbose\n    )\n\n    try:\n        ret = sspauthorcmd.SSPGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in generating markdown for ssp {output}: {e}')\n\n    logger.debug(f'Model {output} markdown generated successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL","title":" ManagedOSCAL ","text":"

                                    Object representing OSCAL models in repository for programmatic manipulation.

                                    Source code in trestle/core/repository.py
                                    class ManagedOSCAL:\n\"\"\"Object representing OSCAL models in repository for programmatic manipulation.\"\"\"\n\n    def __init__(self, root_dir: pathlib.Path, model_type: Type[OscalBaseModel], name: str) -> None:\n\"\"\"Initialize repository OSCAL model object.\"\"\"\n        if not file_utils.is_valid_project_root(root_dir):\n            raise TrestleError(f'Provided root directory {str(root_dir)} is not a valid Trestle root directory.')\n        self.root_dir = root_dir\n        self.model_type = model_type\n        self.model_name = name\n\n        # set model alais and dir\n        self.model_alias = classname_to_alias(self.model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(self.model_alias) is None:\n            raise TrestleError(f'Given model {self.model_alias} is not a top level model.')\n\n        plural_path = ModelUtils.model_type_to_model_dir(self.model_alias)\n        self.model_dir = self.root_dir / plural_path / self.model_name\n\n        if not self.model_dir.exists() or not self.model_dir.is_dir():\n            raise TrestleError(f'Model dir {self.model_name} does not exist.')\n\n        file_content_type = FileContentType.path_to_content_type(self.model_dir / self.model_alias)\n        if file_content_type == FileContentType.UNKNOWN:\n            raise TrestleError(f'Model file for model {self.model_name} does not exist.')\n        self.file_content_type = file_content_type\n\n        filepath = pathlib.Path(\n            self.model_dir,\n            self.model_alias + FileContentType.path_to_file_extension(self.model_dir / self.model_alias)\n        )\n\n        self.filepath = filepath\n\n    def read(self) -> OscalBaseModel:\n\"\"\"Read OSCAL model from repository.\"\"\"\n        logger.debug(f'Reading model {self.model_name}.')\n        model = load_validate_model_path(self.root_dir, self.filepath)\n        return model\n\n    def write(self, model: OscalBaseModel) -> bool:\n\"\"\"Write OSCAL model to repository.\"\"\"\n        logger.debug(f'Writing model {self.model_name}.')\n        model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        # split directory if the model was split\n        split_dir = pathlib.Path(self.model_dir, self.model_alias)\n\n        # Prepare actions; delete split model dir if any, recreate model file, and write to filepath\n        top_element = Element(model)\n        remove_action = RemovePathAction(split_dir)\n        create_action = CreatePathAction(self.filepath, True)\n        write_action = WriteFileAction(self.filepath, top_element, self.file_content_type)\n\n        # create a plan to create the directory and imported file.\n        import_plan = Plan()\n        import_plan.add_action(remove_action)\n        import_plan.add_action(create_action)\n        import_plan.add_action(write_action)\n\n        import_plan.execute()\n\n        logger.debug(f'Model {self.model_name} written to repository')\n        return True\n\n    def split(self, model_file: pathlib.Path, elements: List[str]) -> bool:\n\"\"\"Split the given OSCAL model file in repository.\n\n        Model file path should be relative to the main model directory, e.g., model dir is $TRESTLE_ROOT/catalogs/NIST\n        then model file path can be 'catalog/metadata.json' if metadata is to be split.\n\n        Elements should be specified relative to model file, e.g., 'metadata.props.*'\n        \"\"\"\n        logger.debug(f'Splitting model {self.model_name}, file {model_file}.')\n        # input model_file should be relative to the model dir\n        model_file_path = self.model_dir / model_file\n        model_file_path = model_file_path.resolve()\n        file_parent = model_file_path.parent\n        filename = model_file_path.name\n\n        elems = ''\n        first = True\n        for elem in elements:\n            if first:\n                elems = elem\n                first = False\n            else:\n                elems = elems + ',' + elem\n\n        success = False\n        try:\n            ret = splitcmd.SplitCmd().perform_split(file_parent, filename, elems, self.root_dir)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in splitting model: {e}')\n\n        logger.debug(f'Model {self.model_name}, file {model_file} splitted successfully.')\n        return success\n\n    def merge(self, elements: List[str], parent_model_dir: Optional[pathlib.Path] = None) -> bool:\n\"\"\"Merge OSCAL elements in repository.\n\n        The parent_model_dir specifies the parent model direcotry in which to merge relative to main model dir.\n        For example, if we have to merge 'metadata.*' into 'metadata' then parent_model_dir should be the 'catalog'\n        dir that contains the 'metadata.json' file or the 'metadata' directory\n        \"\"\"\n        logger.debug(f'Merging model {self.model_name}, parent dir {parent_model_dir}.')\n        if parent_model_dir is None:\n            effective_cwd = self.model_dir\n        else:\n            effective_cwd = self.model_dir / parent_model_dir\n\n        success = True\n        try:\n            for elem in elements:\n                plan = mergecmd.MergeCmd.merge(effective_cwd, ElementPath(elem), self.root_dir)\n                plan.execute()\n\n        except Exception as e:\n            raise TrestleError(f'Error in merging model: {e}')\n\n        logger.debug(f'Model {self.model_name} merged successfully.')\n        return success\n\n    def validate(self) -> bool:\n\"\"\"Validate OSCAL model in repository.\"\"\"\n        logger.debug(f'Validating model {self.model_name}.')\n        repo = Repository(self.root_dir)\n        success = repo.validate_model(self.model_type, self.model_name)\n        return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.__init__","title":"__init__(self, root_dir, model_type, name) special","text":"

                                    Initialize repository OSCAL model object.

                                    Source code in trestle/core/repository.py
                                    def __init__(self, root_dir: pathlib.Path, model_type: Type[OscalBaseModel], name: str) -> None:\n\"\"\"Initialize repository OSCAL model object.\"\"\"\n    if not file_utils.is_valid_project_root(root_dir):\n        raise TrestleError(f'Provided root directory {str(root_dir)} is not a valid Trestle root directory.')\n    self.root_dir = root_dir\n    self.model_type = model_type\n    self.model_name = name\n\n    # set model alais and dir\n    self.model_alias = classname_to_alias(self.model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(self.model_alias) is None:\n        raise TrestleError(f'Given model {self.model_alias} is not a top level model.')\n\n    plural_path = ModelUtils.model_type_to_model_dir(self.model_alias)\n    self.model_dir = self.root_dir / plural_path / self.model_name\n\n    if not self.model_dir.exists() or not self.model_dir.is_dir():\n        raise TrestleError(f'Model dir {self.model_name} does not exist.')\n\n    file_content_type = FileContentType.path_to_content_type(self.model_dir / self.model_alias)\n    if file_content_type == FileContentType.UNKNOWN:\n        raise TrestleError(f'Model file for model {self.model_name} does not exist.')\n    self.file_content_type = file_content_type\n\n    filepath = pathlib.Path(\n        self.model_dir,\n        self.model_alias + FileContentType.path_to_file_extension(self.model_dir / self.model_alias)\n    )\n\n    self.filepath = filepath\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.merge","title":"merge(self, elements, parent_model_dir=None)","text":"

                                    Merge OSCAL elements in repository.

                                    The parent_model_dir specifies the parent model direcotry in which to merge relative to main model dir. For example, if we have to merge 'metadata.*' into 'metadata' then parent_model_dir should be the 'catalog' dir that contains the 'metadata.json' file or the 'metadata' directory

                                    Source code in trestle/core/repository.py
                                    def merge(self, elements: List[str], parent_model_dir: Optional[pathlib.Path] = None) -> bool:\n\"\"\"Merge OSCAL elements in repository.\n\n    The parent_model_dir specifies the parent model direcotry in which to merge relative to main model dir.\n    For example, if we have to merge 'metadata.*' into 'metadata' then parent_model_dir should be the 'catalog'\n    dir that contains the 'metadata.json' file or the 'metadata' directory\n    \"\"\"\n    logger.debug(f'Merging model {self.model_name}, parent dir {parent_model_dir}.')\n    if parent_model_dir is None:\n        effective_cwd = self.model_dir\n    else:\n        effective_cwd = self.model_dir / parent_model_dir\n\n    success = True\n    try:\n        for elem in elements:\n            plan = mergecmd.MergeCmd.merge(effective_cwd, ElementPath(elem), self.root_dir)\n            plan.execute()\n\n    except Exception as e:\n        raise TrestleError(f'Error in merging model: {e}')\n\n    logger.debug(f'Model {self.model_name} merged successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.read","title":"read(self)","text":"

                                    Read OSCAL model from repository.

                                    Source code in trestle/core/repository.py
                                    def read(self) -> OscalBaseModel:\n\"\"\"Read OSCAL model from repository.\"\"\"\n    logger.debug(f'Reading model {self.model_name}.')\n    model = load_validate_model_path(self.root_dir, self.filepath)\n    return model\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.split","title":"split(self, model_file, elements)","text":"

                                    Split the given OSCAL model file in repository.

                                    Model file path should be relative to the main model directory, e.g., model dir is $TRESTLE_ROOT/catalogs/NIST then model file path can be 'catalog/metadata.json' if metadata is to be split.

                                    Elements should be specified relative to model file, e.g., 'metadata.props.*'

                                    Source code in trestle/core/repository.py
                                    def split(self, model_file: pathlib.Path, elements: List[str]) -> bool:\n\"\"\"Split the given OSCAL model file in repository.\n\n    Model file path should be relative to the main model directory, e.g., model dir is $TRESTLE_ROOT/catalogs/NIST\n    then model file path can be 'catalog/metadata.json' if metadata is to be split.\n\n    Elements should be specified relative to model file, e.g., 'metadata.props.*'\n    \"\"\"\n    logger.debug(f'Splitting model {self.model_name}, file {model_file}.')\n    # input model_file should be relative to the model dir\n    model_file_path = self.model_dir / model_file\n    model_file_path = model_file_path.resolve()\n    file_parent = model_file_path.parent\n    filename = model_file_path.name\n\n    elems = ''\n    first = True\n    for elem in elements:\n        if first:\n            elems = elem\n            first = False\n        else:\n            elems = elems + ',' + elem\n\n    success = False\n    try:\n        ret = splitcmd.SplitCmd().perform_split(file_parent, filename, elems, self.root_dir)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in splitting model: {e}')\n\n    logger.debug(f'Model {self.model_name}, file {model_file} splitted successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.validate","title":"validate(self)","text":"

                                    Validate OSCAL model in repository.

                                    Source code in trestle/core/repository.py
                                    def validate(self) -> bool:\n\"\"\"Validate OSCAL model in repository.\"\"\"\n    logger.debug(f'Validating model {self.model_name}.')\n    repo = Repository(self.root_dir)\n    success = repo.validate_model(self.model_type, self.model_name)\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.write","title":"write(self, model)","text":"

                                    Write OSCAL model to repository.

                                    Source code in trestle/core/repository.py
                                    def write(self, model: OscalBaseModel) -> bool:\n\"\"\"Write OSCAL model to repository.\"\"\"\n    logger.debug(f'Writing model {self.model_name}.')\n    model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    # split directory if the model was split\n    split_dir = pathlib.Path(self.model_dir, self.model_alias)\n\n    # Prepare actions; delete split model dir if any, recreate model file, and write to filepath\n    top_element = Element(model)\n    remove_action = RemovePathAction(split_dir)\n    create_action = CreatePathAction(self.filepath, True)\n    write_action = WriteFileAction(self.filepath, top_element, self.file_content_type)\n\n    # create a plan to create the directory and imported file.\n    import_plan = Plan()\n    import_plan.add_action(remove_action)\n    import_plan.add_action(create_action)\n    import_plan.add_action(write_action)\n\n    import_plan.execute()\n\n    logger.debug(f'Model {self.model_name} written to repository')\n    return True\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository","title":" Repository ","text":"

                                    Repository class for performing operations on Trestle repository.

                                    This class provides a set of APIs to perform operations on trestle repository programmatically rather than using the command line. It takes the trestle root directory as input while creating an instance of this object. Operations such as import and get model return a ManagedOSCAL object representing the specific model that can be used to perform operations on the specific models.

                                    Source code in trestle/core/repository.py
                                    class Repository:\n\"\"\"Repository class for performing operations on Trestle repository.\n\n    This class provides a set of APIs to perform operations on trestle repository programmatically\n    rather than using the command line. It takes the trestle root directory as input while creating\n    an instance of this object. Operations such as import and get model return a ManagedOSCAL object\n    representing the specific model that can be used to perform operations on the specific models.\n\n    \"\"\"\n\n    def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n        if not file_utils.is_valid_project_root(root_dir):\n            raise TrestleError(f'Provided root directory {root_dir} is not a valid Trestle root directory.')\n        self.root_dir = root_dir\n\n    def import_model(\n        self, model: OscalBaseModel, name: str, content_type: FileContentType = FileContentType.JSON\n    ) -> ManagedOSCAL:\n\"\"\"Import OSCAL object into trestle repository.\"\"\"\n        logger.debug(f'Importing model {name} of type {model.__class__.__name__}.')\n        model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        # Work out output directory and file\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n        desired_model_dir = self.root_dir / plural_path\n        desired_model_path = desired_model_dir / name / (model_alias + FileContentType.to_file_extension(content_type))\n        desired_model_path = desired_model_path.resolve()\n\n        if desired_model_path.exists():\n            raise TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n        content_type = FileContentType.to_content_type(pathlib.Path(desired_model_path).suffix)\n\n        # Prepare actions\n        top_element = Element(model)\n        create_action = CreatePathAction(desired_model_path, True)\n        write_action = WriteFileAction(desired_model_path, top_element, content_type)\n\n        # create a plan to create the directory and imported file.\n        import_plan = Plan()\n        import_plan.add_action(create_action)\n        import_plan.add_action(write_action)\n        import_plan.execute()\n\n        # Validate the imported file, rollback if unsuccessful\n        success = False\n        errmsg = ''\n        try:\n            success = self.validate_model(model.__class__, name)\n            if not success:\n                errmsg = f'Validation of model {name} did not pass'\n                logger.error(errmsg)\n        except Exception as err:\n            logger.error(errmsg)\n            errmsg = f'Import of model {name} failed. Validation failed with error: {err}'\n\n        if not success:\n            # rollback in case of validation error or failure\n            logger.debug(f'Rolling back import of model {name} to {desired_model_path}')\n            try:\n                import_plan.rollback()\n            except TrestleError as err:\n                logger.error(f'Failed to rollback: {err}. Remove {desired_model_path} to resolve state.')\n            else:\n                logger.debug(f'Successful rollback of import to {desired_model_path}')\n\n            # raise trestle error\n            raise TrestleError(errmsg)\n\n        # all well; model was imported and validated successfully\n        logger.debug(f'Model {name} of type {model.__class__.__name__} imported successfully.')\n        return ManagedOSCAL(self.root_dir, model.__class__, name)\n\n    def load_and_import_model(\n        self,\n        model_path: pathlib.Path,\n        name: str,\n        content_type: FileContentType = FileContentType.JSON\n    ) -> ManagedOSCAL:\n\"\"\"Load the model at the specified path into trestle with the specified name.\"\"\"\n        fetcher = cache.FetcherFactory.get_fetcher(self.root_dir, str(model_path))\n        model, _ = fetcher.get_oscal(True)\n\n        return self.import_model(model, name, content_type)\n\n    def list_models(self, model_type: Type[OscalBaseModel]) -> List[str]:\n\"\"\"List models of a given type in trestle repository.\"\"\"\n        logger.debug(f'Listing models of type {model_type.__name__}.')\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n        models = ModelUtils.get_models_of_type(model_alias, self.root_dir)\n\n        return models\n\n    def get_model(self, model_type: Type[OscalBaseModel], name: str) -> ManagedOSCAL:\n\"\"\"Get a specific OSCAL model from repository.\"\"\"\n        logger.debug(f'Getting model {name} of type {model_type.__name__}.')\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n        desired_model_dir = self.root_dir / plural_path / name\n\n        if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n            raise TrestleError(f'Model {name} does not exist.')\n\n        return ManagedOSCAL(self.root_dir, model_type, name)\n\n    def delete_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Delete an OSCAL model from repository.\"\"\"\n        logger.debug(f'Deleting model {name} of type {model_type.__name__}.')\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n        desired_model_dir = self.root_dir / plural_path / name\n\n        if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n            raise TrestleError(f'Model {name} does not exist.')\n        shutil.rmtree(desired_model_dir)\n\n        # remove model from dist directory if it exists\n        dist_model_dir = self.root_dir / const.TRESTLE_DIST_DIR / plural_path\n        file_content_type = FileContentType.path_to_content_type(dist_model_dir / name)\n        if file_content_type != FileContentType.UNKNOWN:\n            file_path = pathlib.Path(\n                dist_model_dir, name + FileContentType.path_to_file_extension(dist_model_dir / name)\n            )\n            logger.debug(f'Deleting model {name} from dist directory.')\n            os.remove(file_path)\n\n        logger.debug(f'Model {name} deleted successfully.')\n        return True\n\n    def assemble_model(self, model_type: Type[OscalBaseModel], name: str, extension: str = 'json') -> bool:\n\"\"\"Assemble an OSCAL model in repository and publish it to 'dist' directory.\"\"\"\n        logger.debug(f'Assembling model {name} of type {model_type.__name__}.')\n        success = False\n\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            type=model_alias, name=name, extension=extension, trestle_root=self.root_dir, verbose=verbose\n        )\n\n        try:\n            ret = assemblecmd.AssembleCmd().assemble_model(model_alias, args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in assembling model: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def validate_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Validate an OSCAL model in repository.\"\"\"\n        logger.debug(f'Validating model {name} of type {model_type.__name__}.')\n        success = False\n\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(type=model_alias, name=name, trestle_root=self.root_dir, verbose=verbose, quiet=False)\n\n        try:\n            ret = validatecmd.ValidateCmd()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in validating model: {e}')\n\n        logger.debug(f'Model {name} validated successfully.')\n        return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.__init__","title":"__init__(self, root_dir) special","text":"

                                    Initialize trestle repository object.

                                    Source code in trestle/core/repository.py
                                    def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n    if not file_utils.is_valid_project_root(root_dir):\n        raise TrestleError(f'Provided root directory {root_dir} is not a valid Trestle root directory.')\n    self.root_dir = root_dir\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.assemble_model","title":"assemble_model(self, model_type, name, extension='json')","text":"

                                    Assemble an OSCAL model in repository and publish it to 'dist' directory.

                                    Source code in trestle/core/repository.py
                                    def assemble_model(self, model_type: Type[OscalBaseModel], name: str, extension: str = 'json') -> bool:\n\"\"\"Assemble an OSCAL model in repository and publish it to 'dist' directory.\"\"\"\n    logger.debug(f'Assembling model {name} of type {model_type.__name__}.')\n    success = False\n\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        type=model_alias, name=name, extension=extension, trestle_root=self.root_dir, verbose=verbose\n    )\n\n    try:\n        ret = assemblecmd.AssembleCmd().assemble_model(model_alias, args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in assembling model: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.delete_model","title":"delete_model(self, model_type, name)","text":"

                                    Delete an OSCAL model from repository.

                                    Source code in trestle/core/repository.py
                                    def delete_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Delete an OSCAL model from repository.\"\"\"\n    logger.debug(f'Deleting model {name} of type {model_type.__name__}.')\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n    desired_model_dir = self.root_dir / plural_path / name\n\n    if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n        raise TrestleError(f'Model {name} does not exist.')\n    shutil.rmtree(desired_model_dir)\n\n    # remove model from dist directory if it exists\n    dist_model_dir = self.root_dir / const.TRESTLE_DIST_DIR / plural_path\n    file_content_type = FileContentType.path_to_content_type(dist_model_dir / name)\n    if file_content_type != FileContentType.UNKNOWN:\n        file_path = pathlib.Path(\n            dist_model_dir, name + FileContentType.path_to_file_extension(dist_model_dir / name)\n        )\n        logger.debug(f'Deleting model {name} from dist directory.')\n        os.remove(file_path)\n\n    logger.debug(f'Model {name} deleted successfully.')\n    return True\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.get_model","title":"get_model(self, model_type, name)","text":"

                                    Get a specific OSCAL model from repository.

                                    Source code in trestle/core/repository.py
                                    def get_model(self, model_type: Type[OscalBaseModel], name: str) -> ManagedOSCAL:\n\"\"\"Get a specific OSCAL model from repository.\"\"\"\n    logger.debug(f'Getting model {name} of type {model_type.__name__}.')\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n    desired_model_dir = self.root_dir / plural_path / name\n\n    if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n        raise TrestleError(f'Model {name} does not exist.')\n\n    return ManagedOSCAL(self.root_dir, model_type, name)\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.import_model","title":"import_model(self, model, name, content_type=<FileContentType.JSON: 1>)","text":"

                                    Import OSCAL object into trestle repository.

                                    Source code in trestle/core/repository.py
                                    def import_model(\n    self, model: OscalBaseModel, name: str, content_type: FileContentType = FileContentType.JSON\n) -> ManagedOSCAL:\n\"\"\"Import OSCAL object into trestle repository.\"\"\"\n    logger.debug(f'Importing model {name} of type {model.__class__.__name__}.')\n    model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    # Work out output directory and file\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n    desired_model_dir = self.root_dir / plural_path\n    desired_model_path = desired_model_dir / name / (model_alias + FileContentType.to_file_extension(content_type))\n    desired_model_path = desired_model_path.resolve()\n\n    if desired_model_path.exists():\n        raise TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n    content_type = FileContentType.to_content_type(pathlib.Path(desired_model_path).suffix)\n\n    # Prepare actions\n    top_element = Element(model)\n    create_action = CreatePathAction(desired_model_path, True)\n    write_action = WriteFileAction(desired_model_path, top_element, content_type)\n\n    # create a plan to create the directory and imported file.\n    import_plan = Plan()\n    import_plan.add_action(create_action)\n    import_plan.add_action(write_action)\n    import_plan.execute()\n\n    # Validate the imported file, rollback if unsuccessful\n    success = False\n    errmsg = ''\n    try:\n        success = self.validate_model(model.__class__, name)\n        if not success:\n            errmsg = f'Validation of model {name} did not pass'\n            logger.error(errmsg)\n    except Exception as err:\n        logger.error(errmsg)\n        errmsg = f'Import of model {name} failed. Validation failed with error: {err}'\n\n    if not success:\n        # rollback in case of validation error or failure\n        logger.debug(f'Rolling back import of model {name} to {desired_model_path}')\n        try:\n            import_plan.rollback()\n        except TrestleError as err:\n            logger.error(f'Failed to rollback: {err}. Remove {desired_model_path} to resolve state.')\n        else:\n            logger.debug(f'Successful rollback of import to {desired_model_path}')\n\n        # raise trestle error\n        raise TrestleError(errmsg)\n\n    # all well; model was imported and validated successfully\n    logger.debug(f'Model {name} of type {model.__class__.__name__} imported successfully.')\n    return ManagedOSCAL(self.root_dir, model.__class__, name)\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.list_models","title":"list_models(self, model_type)","text":"

                                    List models of a given type in trestle repository.

                                    Source code in trestle/core/repository.py
                                    def list_models(self, model_type: Type[OscalBaseModel]) -> List[str]:\n\"\"\"List models of a given type in trestle repository.\"\"\"\n    logger.debug(f'Listing models of type {model_type.__name__}.')\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n    models = ModelUtils.get_models_of_type(model_alias, self.root_dir)\n\n    return models\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.load_and_import_model","title":"load_and_import_model(self, model_path, name, content_type=<FileContentType.JSON: 1>)","text":"

                                    Load the model at the specified path into trestle with the specified name.

                                    Source code in trestle/core/repository.py
                                    def load_and_import_model(\n    self,\n    model_path: pathlib.Path,\n    name: str,\n    content_type: FileContentType = FileContentType.JSON\n) -> ManagedOSCAL:\n\"\"\"Load the model at the specified path into trestle with the specified name.\"\"\"\n    fetcher = cache.FetcherFactory.get_fetcher(self.root_dir, str(model_path))\n    model, _ = fetcher.get_oscal(True)\n\n    return self.import_model(model, name, content_type)\n
                                    "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.validate_model","title":"validate_model(self, model_type, name)","text":"

                                    Validate an OSCAL model in repository.

                                    Source code in trestle/core/repository.py
                                    def validate_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Validate an OSCAL model in repository.\"\"\"\n    logger.debug(f'Validating model {name} of type {model_type.__name__}.')\n    success = False\n\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(type=model_alias, name=name, trestle_root=self.root_dir, verbose=verbose, quiet=False)\n\n    try:\n        ret = validatecmd.ValidateCmd()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in validating model: {e}')\n\n    logger.debug(f'Model {name} validated successfully.')\n    return success\n
                                    "},{"location":"api_reference/trestle.core.resolver.merge/","title":"merge","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge","title":"trestle.core.resolver.merge","text":"

                                    Create resolved catalog from profile.

                                    "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.CATALOG_EXCLUDE","title":"CATALOG_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.CONTROL_EXCLUDE","title":"CONTROL_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.ID","title":"ID","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.ITEM_EXCLUDE_MAP","title":"ITEM_EXCLUDE_MAP","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.NAME","title":"NAME","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.PARAMETER_EXCLUDE","title":"PARAMETER_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.PART_EXCLUDE","title":"PART_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.PROPERTY_EXCLUDE","title":"PROPERTY_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge","title":" Merge (Filter) ","text":"

                                    Merge the incoming catalogs according to rules in the profile.

                                    The incoming catalogs have already been pruned based on the import. Now the controls must be gathered, merged, and grouped based on the merge settings.

                                    Source code in trestle/core/resolver/merge.py
                                    class Merge(Pipeline.Filter):\n\"\"\"\n    Merge the incoming catalogs according to rules in the profile.\n\n    The incoming catalogs have already been pruned based on the import.\n    Now the controls must be gathered, merged, and grouped based on the merge settings.\n    \"\"\"\n\n    def __init__(self, profile: prof.Profile) -> None:\n\"\"\"Initialize the class with the profile.\"\"\"\n        logger.debug('merge filter initialize')\n        self._profile = profile\n\n    def _get_id(self, item: OBT) -> Optional[str]:\n        id_ = getattr(item, ID, None)\n        if id_ is None:\n            id_ = getattr(item, NAME, None)\n        return id_\n\n    def _item_genertor(self, dest: List[OBT], src: List[OBT], merge_method: Optional[str]) -> Iterator[OBT]:\n        if merge_method == prof.CombinationMethodValidValues.keep.value:\n            dest.extend(src)\n        else:\n            for item in src:\n                # if there is an exact copy of this in dest then ignore it\n                if item not in dest:\n                    yield item\n\n    def _merge_item(self, item: OBT, dest: List[OBT], merge_method: Optional[str]) -> bool:\n        merged = False\n        item_id = self._get_id(item)\n        if item_id is not None:\n            for other in dest:\n                other_id = self._get_id(other)\n                if other_id != item_id:\n                    continue\n                if merge_method == prof.CombinationMethodValidValues.merge.value:\n                    self._merge_items(other, item, merge_method)\n                merged = True\n                break\n        return merged\n\n    def _merge_lists(self, dest: List[OBT], src: List[OBT], merge_method: Optional[str]) -> None:\n        added_items = []\n        if merge_method == prof.CombinationMethodValidValues.keep.value:\n            dest.extend(src)\n            return\n        for item in self._item_genertor(dest, src, merge_method):\n            merged = self._merge_item(item, dest, merge_method)\n            # it isn't already in dest and no match was found for merge, so append\n            if not merged:\n                added_items.append(item)\n        dest.extend(added_items)\n\n    def _merge_attrs(\n        self, dest: Union[OBT, List[OBT]], src: Union[OBT, List[OBT]], attr: str, merge_method: Optional[str]\n    ) -> None:\n\"\"\"Merge this attr of src into the attr of dest.\"\"\"\n        src_attr = getattr(src, attr, None)\n        if src_attr is None:\n            return\n        item_type = type(src).__name__\n        if attr in ITEM_EXCLUDE_MAP.get(item_type, []):\n            return\n        dest_attr = getattr(dest, attr, None)\n        if dest_attr and isinstance(dest_attr, list):\n            self._merge_lists(dest_attr, src_attr, merge_method)\n            setattr(dest, attr, dest_attr)\n            return\n        if dest_attr and merge_method == prof.CombinationMethodValidValues.use_first.value:\n            return\n        if dest_attr == src_attr and merge_method not in [None, prof.CombinationMethodValidValues.keep.value]:\n            return\n        setattr(dest, attr, src_attr)\n\n    def _merge_items(self, dest: OBT, src: OBT, merge_method: Optional[str]) -> None:\n\"\"\"Merge two items recursively.\"\"\"\n        for field in src.__fields_set__:\n            self._merge_attrs(dest, src, field, merge_method)\n\n    def _group_contents(self, group: cat.Group) -> Tuple[List[cat.Control], List[com.Parameter]]:\n\"\"\"Get flattened content of group and its groups recursively.\"\"\"\n        controls = []\n        params = []\n        controls.extend(as_list(group.controls))\n        params.extend(as_list(group.params))\n        if group.groups is not None:\n            for sub_group in group.groups:\n                new_controls, new_params = self._group_contents(sub_group)\n                controls.extend(new_controls)\n                params.extend(new_params)\n        return controls, params\n\n    def _flatten_catalog(self, catalog: cat.Catalog, as_is: bool) -> cat.Catalog:\n\"\"\"Flatten the groups of the catalog if as_is is False.\"\"\"\n        if as_is or catalog.groups is None:\n            return catalog\n\n        # as_is is False so flatten the controls into a single list\n        catalog.controls = as_list(catalog.controls)\n        catalog.params = as_list(catalog.params)\n        for group in catalog.groups:\n            new_controls, new_params = self._group_contents(group)\n            catalog.controls.extend(new_controls)\n            catalog.params.extend(new_params)\n        catalog.controls = none_if_empty(catalog.controls)\n        catalog.params = none_if_empty(catalog.params)\n        catalog.groups = None\n        return catalog\n\n    def _merge_two_catalogs(\n        self, dest: cat.Catalog, src: cat.Catalog, merge_method: Optional[str], as_is: bool\n    ) -> cat.Catalog:\n        # merge_method is use_first, merge, keep\n        # no combine or merge_method equates to merge_method=keep\n        # if as_is is false, the result is flattened\n\n        dest = self._flatten_catalog(dest, as_is)\n        src = self._flatten_catalog(src, as_is)\n\n        self._merge_items(dest, src, merge_method)\n\n        return dest\n\n    def _merge_catalog(self, merged: Optional[cat.Catalog], catalog: cat.Catalog) -> cat.Catalog:\n\"\"\"Merge the controls in the catalog into merged catalog.\"\"\"\n        # no merge means keep, including dups\n        # same for merge with no combine\n        # groups are merged only if separate directive such as as-is is given\n        # use-first is a merge combination rule\n        # merge is a merge combination rule for controls.  groups are not merged by this rule\n        # merge/as-is and merge/custom are used for merging groups\n        # if neither as-is nor custom is specified - just get single list of controls\n        # unstructured controls should appear after any loose params\n\n        # make copies to avoid changing input objects\n        local_cat = catalog.copy(deep=True)\n        local_merged = merged.copy(deep=True) if merged else None\n\n        merge_method = prof.CombinationMethodValidValues.keep.value\n        as_is = False\n        if self._profile.merge is not None:\n            if self._profile.merge.custom is not None:\n                raise TrestleError('Profile with custom merge is not supported.')\n            if self._profile.merge.as_is is not None:\n                as_is = self._profile.merge.as_is\n            if self._profile.merge.combine is None:\n                logger.debug('Profile has merge but no combine so defaulting to combine/merge.')\n                merge_method = prof.CombinationMethodValidValues.merge.value\n            else:\n                merge_combine = self._profile.merge.combine\n                if merge_combine.method.value is None:\n                    logger.debug('Profile has merge combine but no method.  Defaulting to merge.')\n                    merge_method = prof.CombinationMethodValidValues.merge.value\n                else:\n                    merge_method = merge_combine.method.value\n\n        if local_merged is None:\n            return self._flatten_catalog(local_cat, as_is)\n\n        # merge the incoming catalog with merged based on merge_method and as_is\n        return self._merge_two_catalogs(local_merged, local_cat, merge_method, as_is)\n\n    def process(self, pipelines: List[Pipeline]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n        Merge the incoming catalogs.\n\n        This pulls from import and iterates over the incoming catalogs.\n        The way groups, lists of controls, and controls themselves get merged is specified by the profile.\n        \"\"\"\n        merged: Optional[cat.Catalog] = None\n        logger.debug(f'merge entering process with {len(pipelines)} pipelines')\n        for pipeline in pipelines:\n            catalog = next(pipeline.process(None))\n            merged = self._merge_catalog(merged, catalog)\n        yield merged  # type: ignore\n
                                    "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge.__init__","title":"__init__(self, profile) special","text":"

                                    Initialize the class with the profile.

                                    Source code in trestle/core/resolver/merge.py
                                    def __init__(self, profile: prof.Profile) -> None:\n\"\"\"Initialize the class with the profile.\"\"\"\n    logger.debug('merge filter initialize')\n    self._profile = profile\n
                                    "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge.process","title":"process(self, pipelines)","text":"

                                    Merge the incoming catalogs.

                                    This pulls from import and iterates over the incoming catalogs. The way groups, lists of controls, and controls themselves get merged is specified by the profile.

                                    Source code in trestle/core/resolver/merge.py
                                    def process(self, pipelines: List[Pipeline]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n    Merge the incoming catalogs.\n\n    This pulls from import and iterates over the incoming catalogs.\n    The way groups, lists of controls, and controls themselves get merged is specified by the profile.\n    \"\"\"\n    merged: Optional[cat.Catalog] = None\n    logger.debug(f'merge entering process with {len(pipelines)} pipelines')\n    for pipeline in pipelines:\n        catalog = next(pipeline.process(None))\n        merged = self._merge_catalog(merged, catalog)\n    yield merged  # type: ignore\n
                                    "},{"location":"api_reference/trestle.core.resolver.modify/","title":"modify","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify","title":"trestle.core.resolver.modify","text":"

                                    Create resolved catalog from profile.

                                    "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify","title":" Modify (Filter) ","text":"

                                    Modify the controls based on the profile.

                                    Source code in trestle/core/resolver/modify.py
                                    class Modify(Pipeline.Filter):\n\"\"\"Modify the controls based on the profile.\"\"\"\n\n    def __init__(\n        self,\n        profile: prof.Profile,\n        change_prose: bool = False,\n        block_adds: bool = False,\n        block_params: bool = False,\n        params_format: str = None,\n        param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Initialize the filter.\"\"\"\n        self._profile = profile\n        self._catalog_interface: Optional[CatalogInterface] = None\n        self._block_adds = block_adds\n        self._block_params = block_params\n        self._change_prose = change_prose\n        self._params_format = params_format\n        self._param_rep = param_rep\n        self.show_value_warnings = show_value_warnings\n        self._value_assigned_prefix = value_assigned_prefix\n        self._value_not_assigned_prefix = value_not_assigned_prefix\n        logger.debug(f'modify initialize filter with profile {profile.metadata.title}')\n\n    @staticmethod\n    def _add_adds_to_part(part: common.Part, add: prof.Add, added_parts=False) -> None:\n        for attr in ['params', 'props', 'parts', 'links']:\n            # don't add parts if already added earlier\n            if added_parts and attr == 'parts':\n                continue\n            add_list = getattr(add, attr, None)\n            if add_list:\n                Modify._add_attr_to_part(part, add_list[:], attr, add.position)\n\n    @staticmethod\n    def _add_to_list(parts_list: List[common.Part], add: prof.Add) -> bool:\n\"\"\"Add the contents of the add according to its by_id and position.\n\n        Return True on success or False if id needed and not found.\n\n        This is only called when by_id is not None.\n        The add will be inserted if the id is found, or return False if not.\n        This allows a separate recursive routine to search sub-lists for the id.\n        Position before/after will put the item adjacent to the target in the same list as target\n        Position starting/ending will put the item within the target itself\n        \"\"\"\n        # Test here for matched by_id attribute.\n        added_parts = False\n        for index in range(len(parts_list)):\n            # find the matching part\n            if parts_list[index].id == add.by_id:\n                if add.position == prof.PositionValidValues.after:\n                    for offset, new_item in enumerate(as_list(add.parts)):\n                        parts_list.insert(index + 1 + offset, new_item)\n                    added_parts = True\n                elif add.position == prof.PositionValidValues.before:\n                    for offset, new_item in enumerate(as_list(add.parts)):\n                        parts_list.insert(index + offset, new_item)\n                    added_parts = True\n                # if starting or ending or None, the adds go directly into this part according to type\n                Modify._add_adds_to_part(parts_list[index], add, added_parts)\n                return True\n        return False\n\n    @staticmethod\n    def _add_to_parts(parts: List[common.Part], add: prof.Add) -> bool:\n\"\"\"\n        Add the add to the parts.\n\n        This is only called if add.by_id is not None.\n        \"\"\"\n        if Modify._add_to_list(parts, add):\n            return True\n        for part in parts:\n            if part.parts is not None and Modify._add_to_parts(part.parts, add):\n                return True\n        return False\n\n    @staticmethod\n    def _add_attr_to_part(part: common.Part, items: List[OBT], attr: str, position: Optional[str]) -> None:\n        attr_list = as_list(getattr(part, attr, None))\n        # position may be None and if so will go at end\n        if position in [prof.PositionValidValues.starting, prof.PositionValidValues.before]:\n            items.extend(attr_list)\n            attr_list = items\n        else:\n            attr_list.extend(items)\n        setattr(part, attr, attr_list)\n\n    @staticmethod\n    def _add_attr_to_control(control: cat.Control, items: List[OBT], attr: str, position: Optional[str]) -> None:\n        attr_list = as_list(getattr(control, attr, None))\n        if position in [prof.PositionValidValues.starting, prof.PositionValidValues.before]:\n            items.extend(attr_list)\n            attr_list = items\n        else:\n            attr_list.extend(items)\n        setattr(control, attr, attr_list)\n\n    @staticmethod\n    def _add_to_trestle_props(control: cat.Control, add: prof.Add) -> None:\n\"\"\"Add props to special trestle part that keeps track of inherited props.\"\"\"\n        if add.props:\n            trestle_part = get_item_from_list(control.parts, TRESTLE_INHERITED_PROPS_TRACKER, lambda p: p.name)\n            if trestle_part is None:\n                trestle_part = common.Part(\n                    id=TRESTLE_INHERITED_PROPS_TRACKER, name=TRESTLE_INHERITED_PROPS_TRACKER, props=[], parts=[]\n                )\n                control.parts = as_list(control.parts)\n                control.parts.append(trestle_part)\n                trestle_part = control.parts[-1]\n            if add.by_id is None or add.by_id == control.id:\n                trestle_part.props.extend(add.props)\n            else:\n                by_id_part = get_item_from_list(trestle_part.parts, add.by_id, lambda p: p.title)\n                if by_id_part is None:\n                    trestle_part.parts.append(\n                        common.Part(name=TRESTLE_INHERITED_PROPS_TRACKER + '_' + add.by_id, title=add.by_id, props=[])\n                    )\n                    by_id_part = trestle_part.parts[-1]\n                by_id_part.props.extend(add.props)\n\n    @staticmethod\n    def _add_to_control(control: cat.Control, add: prof.Add) -> None:\n\"\"\"First step in applying Add to control.\"\"\"\n        control.parts = as_list(control.parts)\n        if add.by_id is None or add.by_id == control.id:\n            # add contents will be added to the control directly and with no recursion\n            for attr in ['params', 'props', 'parts', 'links']:\n                add_list = getattr(add, attr, None)\n                if add_list:\n                    Modify._add_attr_to_control(control, add_list[:], attr, add.position)\n        else:\n            # this is only called if by_id is not None\n            if not Modify._add_to_parts(control.parts, add):\n                logger.warning(f'Could not find id for add in control {control.id}: {add.by_id}')\n        Modify._add_to_trestle_props(control, add)\n        control.parts = none_if_empty(control.parts)\n\n    @staticmethod\n    def _set_overwrite_items(param: common.Parameter, set_param: prof.SetParameter) -> None:\n        # these overwrite\n        if set_param.class_:\n            param.class_ = set_param.class_\n        if set_param.depends_on:\n            param.depends_on = set_param.depends_on\n        if set_param.label:\n            param.label = set_param.label\n        if set_param.usage:\n            param.usage = set_param.usage\n        if set_param.values:\n            param.values = set_param.values\n        if set_param.select:\n            param.select = set_param.select\n\n    @staticmethod\n    def _set_appended_items(param: common.Parameter, set_param: prof.SetParameter) -> None:\n        # these append\n        if set_param.constraints:\n            if not param.constraints:\n                param.constraints = []\n            param.constraints.extend(set_param.constraints)\n        if set_param.guidelines:\n            if not param.guidelines:\n                param.guidelines = []\n            param.guidelines.extend(set_param.guidelines)\n\n    @staticmethod\n    def _set_replaced_or_appended_items(param: common.Parameter, set_param: prof.SetParameter) -> None:\n        # these replace or append\n        if set_param.props:\n            new_props = as_list(param.props)\n            names = [prop.name for prop in new_props]\n            for prop in set_param.props:\n                if prop.name in names:\n                    new_props[names.index(prop.name)] = prop\n                else:\n                    new_props.append(prop)\n            param.props = new_props\n        if set_param.links:\n            new_links = as_list(param.links)\n            hrefs = [link.href for link in new_links]\n            for link in set_param.links:\n                if link.href in hrefs:\n                    new_links[hrefs.index(link.href)] = link\n                else:\n                    new_links.append(link)\n            param.links = new_links\n\n    def _set_parameter_in_control_or_loose(self, set_param: prof.SetParameter) -> None:\n\"\"\"\n        Find the control with the param_id in it and set the parameter contents.\n\n        It modifies controls in the control_dict not the catalog.\n        Parameters are either bound to a control or are 'loose' and bound to the catalog itself.\n        \"\"\"\n        # find the target param in control or the catalog's loose ones, i.e. catalog.params\n        control = self._catalog_interface.get_control_by_param_id(set_param.param_id)\n        loose_param = False\n        if control:\n            control.params = as_list(control.params)\n            param_ids = [param.id for param in control.params]\n            if set_param.param_id not in param_ids:\n                raise TrestleNotFoundError(f'Param id {set_param.param_id} not found in control {control.id}')\n            index = param_ids.index(set_param.param_id)\n            param = control.params[index]\n        else:\n            param = self._catalog_interface.loose_param_dict.get(set_param.param_id, None)\n            if param:\n                loose_param = True\n            else:\n                logger.warning(f'SetParameter for param_id {set_param.param_id} not found in catalog')\n                return\n\n        # rules here follow https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/\n        # see 'Modify Phase' and Setting Parameters\n\n        Modify._set_overwrite_items(param, set_param)\n        Modify._set_appended_items(param, set_param)\n        Modify._set_replaced_or_appended_items(param, set_param)\n\n        if loose_param:\n            self._catalog_interface.loose_param_dict[set_param.param_id] = param\n        else:\n            control.params[index] = param\n            self._catalog_interface.replace_control(control)\n\n    def _modify_controls(self, catalog: cat.Catalog) -> cat.Catalog:\n\"\"\"Modify the controls based on the profile.\"\"\"\n        logger.debug(f'modify specify catalog {catalog.metadata.title} for profile {self._profile.metadata.title}')\n        self._catalog_interface = CatalogInterface(catalog)\n        alters: Optional[List[prof.Alter]] = None\n        # find the modify and alters\n        if self._profile.modify:\n            # change all parameter values\n            if self._profile.modify.set_parameters and not self._block_params:\n                set_param_list = self._profile.modify.set_parameters\n                for set_param in set_param_list:\n                    self._set_parameter_in_control_or_loose(set_param)\n            alters = self._profile.modify.alters\n\n        # an add with no by-id applies to the control\n        # if position is starting it should appear immediately after title\n        # if position is ending it should appear at end\n        # if not specified it defaults to ending\n        # if no by-id then before is treated as starting and after is treated as ending\n        if alters is not None:\n            title = self._profile.metadata.title\n            for alter in alters:\n                if alter.control_id is None:\n                    logger.warning(f'Alter must have control id specified in profile {title}.')\n                    continue\n                id_ = alter.control_id\n                if alter.removes is not None:\n                    logger.warning(f'Alter not supported for removes in profile {title} control {id_}')\n                    continue\n                # we want a warning about adds even if adds are blocked, as in profile generate\n                if alter.adds is None:\n                    logger.warning(f'Alter has no adds in profile {title} control {id_}')\n                    continue\n                if not self._block_adds:\n                    for add in alter.adds:\n                        control = self._catalog_interface.get_control(id_)\n                        if control is None:\n                            logger.warning(\n                                f'Alter/Add refers to control {id_} but it is not found in the import '\n                                + f'for profile {self._profile.metadata.title}'\n                            )\n                        else:\n                            self._add_to_control(control, add)\n                            self._catalog_interface.replace_control(control)\n\n        if self._change_prose:\n            # go through all controls and fix the prose based on param values\n            self._catalog_interface._change_prose_with_param_values(\n                self._params_format,\n                self._param_rep,\n                self.show_value_warnings,\n                self._value_assigned_prefix,\n                self._value_not_assigned_prefix\n            )\n\n        catalog = self._catalog_interface.get_catalog()\n\n        # update the original profile metadata with new contents\n        # roles and responsible-parties will be pulled in with new uuid's\n        # the title simply becomes the title of the current profile - and will get overwritten\n        # by any other profiles downstream so that only the final profile title is used\n        new_metadata = self._profile.metadata\n        new_metadata.title = self._profile.metadata.title\n        new_metadata.oscal_version = OSCAL_VERSION\n\n        links: List[common.Link] = []\n        for import_ in self._profile.imports:\n            links.append(common.Link(**{'href': import_.href, 'rel': RESOLUTION_SOURCE}))\n        new_metadata.links = links\n\n        # move catalog controls from dummy group '' into the catalog\n        for group in as_list(catalog.groups):\n            if not group.id:\n                catalog.controls = group.controls\n                catalog.groups.remove(group)\n                break\n\n        catalog.metadata = new_metadata\n\n        return catalog\n\n    def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:\n\"\"\"Make the modifications to the controls based on the profile.\"\"\"\n        catalog = next(catalog_iter)\n        logger.debug(\n            f'modify process with catalog {catalog.metadata.title} using profile {self._profile.metadata.title}'\n        )\n        yield self._modify_controls(catalog)\n
                                    "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify.__init__","title":"__init__(self, profile, change_prose=False, block_adds=False, block_params=False, params_format=None, param_rep=<ParameterRep.LEAVE_MOUSTACHE: 0>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) special","text":"

                                    Initialize the filter.

                                    Source code in trestle/core/resolver/modify.py
                                    def __init__(\n    self,\n    profile: prof.Profile,\n    change_prose: bool = False,\n    block_adds: bool = False,\n    block_params: bool = False,\n    params_format: str = None,\n    param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> None:\n\"\"\"Initialize the filter.\"\"\"\n    self._profile = profile\n    self._catalog_interface: Optional[CatalogInterface] = None\n    self._block_adds = block_adds\n    self._block_params = block_params\n    self._change_prose = change_prose\n    self._params_format = params_format\n    self._param_rep = param_rep\n    self.show_value_warnings = show_value_warnings\n    self._value_assigned_prefix = value_assigned_prefix\n    self._value_not_assigned_prefix = value_not_assigned_prefix\n    logger.debug(f'modify initialize filter with profile {profile.metadata.title}')\n
                                    "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify.process","title":"process(self, catalog_iter)","text":"

                                    Make the modifications to the controls based on the profile.

                                    Source code in trestle/core/resolver/modify.py
                                    def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:\n\"\"\"Make the modifications to the controls based on the profile.\"\"\"\n    catalog = next(catalog_iter)\n    logger.debug(\n        f'modify process with catalog {catalog.metadata.title} using profile {self._profile.metadata.title}'\n    )\n    yield self._modify_controls(catalog)\n
                                    "},{"location":"api_reference/trestle.core.resolver.prune/","title":"prune","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune","title":"trestle.core.resolver.prune","text":"

                                    Create resolved catalog from profile.

                                    "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune","title":" Prune (Filter) ","text":"

                                    Prune the catalog based on the import include rule.

                                    Source code in trestle/core/resolver/prune.py
                                    class Prune(Pipeline.Filter):\n\"\"\"Prune the catalog based on the import include rule.\"\"\"\n\n    def __init__(self, import_: prof.Import, profile: prof.Profile) -> None:\n\"\"\"\n        Inject the import.\n\n        This needs to be created prior to knowing the catalog.\n        The profile itself is only needed for debug messages.\n        The import is one possibly several imports in that profile.\n        \"\"\"\n        self._import = import_\n        self._profile = profile\n        self._catalog_interface: Optional[CatalogInterface] = None\n        self._catalog: Optional[cat.Catalog] = None\n\n    def _set_catalog(self, catalog: cat.Catalog) -> None:\n\"\"\"Set the catalog used by the catalog interface.\"\"\"\n        self._catalog_interface = CatalogInterface(catalog)\n        self._catalog = catalog\n\n    def _controls_selected(self, select_list: Optional[List[prof.SelectControl]]) -> List[str]:\n        control_ids: List[str] = []\n        if select_list is not None:\n            for select_control in select_list:\n                if select_control.matching is not None:\n                    raise TrestleError('Profiles with SelectControl based on matching are not supported.')\n                include_children = select_control.with_child_controls == 'yes'\n                if select_control.with_ids:\n                    new_ids = select_control.with_ids\n                    for withid_ in new_ids:\n                        id_ = withid_.__root__\n                        control_ids.append(id_)\n                        if include_children:\n                            control_ids.extend(self._catalog_interface.get_dependent_control_ids(id_))\n        return control_ids\n\n    def _find_needed_control_ids(self) -> List[str]:\n\"\"\"Get list of control_ids needed by profile and corresponding groups.\"\"\"\n        if self._import.include_controls is not None:\n            include_ids = self._controls_selected(self._import.include_controls)\n        else:\n            if self._import.include_all is None:\n                logger.warning('Profile does not specify include-controls, so including all.')\n            include_ids = self._catalog_interface.get_control_ids()\n\n        exclude_ids = self._controls_selected(self._import.exclude_controls)\n\n        if not set(include_ids).issuperset(set(exclude_ids)):\n            logger.debug(f'include_ids is not a superset of exclude_ids in import {self._import.href}')\n        return sorted([id_ for id_ in include_ids if id_ not in exclude_ids])\n\n    def _prune_control(self, needed_ids: List[str], control: cat.Control, exclude_ids: List[str]) -> cat.Control:\n\"\"\"\n        Prune the control based on the Import requirements.\n\n        This is only called if the control is needed\n        Some or all of its sub_controls may not be needed\n        This always returns the original control, possibly with fewer subcontrols\n        \"\"\"\n        if control.controls is None:\n            return control\n        controls = []\n        for sub_control in control.controls:\n            if sub_control.id in needed_ids and sub_control.id not in exclude_ids:\n                controls.append(self._prune_control(needed_ids, sub_control, exclude_ids))\n                exclude_ids.append(sub_control.id)\n        control.controls = none_if_empty(controls)\n        return control\n\n    def _prune_controls(self, needed_ids: List[str]) -> List[str]:\n        loaded_ids: List[str] = []\n        final_ids: List[str] = []\n        for control_id in needed_ids:\n            if control_id not in loaded_ids:\n                control = self._catalog_interface.get_control(control_id)\n                if control is None:\n                    msg = (\n                        f'Profile titled \"{self._profile.metadata.title}\" references control {control_id} '\n                        f'but it is not in catalog titled \"{self._catalog.metadata.title}\"'\n                    )\n                    raise TrestleError(msg)\n                control = self._prune_control(needed_ids, control, loaded_ids)\n                self._catalog_interface.replace_control(control)\n                loaded_ids.append(control_id)\n                final_ids.append(control_id)\n        return final_ids\n\n    def _re_insert_child_controls(self, control: cat.Control) -> cat.Control:\n\"\"\"Re insert this control and its children recursively.\"\"\"\n        new_controls = []\n        for sub_control in as_list(control.controls):\n            new_control = self._re_insert_child_controls(sub_control)\n            new_controls.append(new_control)\n        control.controls = none_if_empty(new_controls)\n        return control\n\n    def _re_insert_children(self) -> None:\n\"\"\"Go through all controls in control dict and load child controls from control dict.\"\"\"\n        for control in self._catalog_interface.get_all_controls_from_dict():\n            _ = self._re_insert_child_controls(control)\n\n    def _prune_catalog(self) -> cat.Catalog:\n\"\"\"Prune the controls in the current catalog.\"\"\"\n        if self._import is None:\n            return self._catalog\n\n        needed_ids = self._find_needed_control_ids()\n\n        # if a control includes controls - only include those that we know are needed\n        final_control_ids = self._prune_controls(needed_ids)\n\n        self._re_insert_children()\n\n        cat_controls = []\n\n        # build the needed groups of controls\n        group_dict: Dict[str, cat.Group] = {}\n        for control_id in final_control_ids:\n            control = self._catalog_interface.get_control(control_id)\n            group_id, group_title, group_class = self._catalog_interface.get_group_info_by_control(control_id)\n            if not group_id:\n                cat_controls.append(control)\n                continue\n            group = group_dict.get(group_id)\n            if group is None:\n                group = cat.Group(id=group_id, title=group_title, class_=group_class, controls=[control])\n                group_dict[group_id] = group\n            else:\n                group_dict[group_id].controls.append(control)\n\n        new_groups: Optional[List[cat.Group]] = list(group_dict.values())\n\n        # should avoid empty lists so set to None if empty\n        new_groups = none_if_empty(new_groups)\n        cat_controls = none_if_empty(cat_controls)\n        new_params = self._catalog.params\n\n        new_cat = cat.Catalog(\n            uuid=str(uuid4()),\n            metadata=self._catalog.metadata,\n            back_matter=common.BackMatter(),\n            controls=cat_controls,\n            groups=new_groups,\n            params=new_params\n        )\n\n        # find all referenced uuids - they should be 1:1 with those in backmatter\n        needed_uuid_refs = ModelUtils.find_uuid_refs(new_cat)\n\n        # prune the list of resources to only those that are needed\n        new_resources: Optional[List[common.Resource]] = []\n        if self._catalog.back_matter and self._catalog.back_matter.resources:\n            new_resources = [res for res in self._catalog.back_matter.resources if res.uuid in needed_uuid_refs]\n        new_resources = none_if_empty(new_resources)\n        new_cat.back_matter.resources = new_resources\n\n        return new_cat\n\n    def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n        Prune the catalog based on the include rule in the import_.\n\n        This only processes the one catalog yielded by the one import in this pipeline.\n        It must yield in order to have the merge filter loop over available imported catalogs.\n        \"\"\"\n        self._set_catalog(next(catalog_iter))\n        logger.debug(f'prune yielding catalog {self._catalog.metadata.title} with import {self._import.href}')\n        yield self._prune_catalog()\n
                                    "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune.__init__","title":"__init__(self, import_, profile) special","text":"

                                    Inject the import.

                                    This needs to be created prior to knowing the catalog. The profile itself is only needed for debug messages. The import is one possibly several imports in that profile.

                                    Source code in trestle/core/resolver/prune.py
                                    def __init__(self, import_: prof.Import, profile: prof.Profile) -> None:\n\"\"\"\n    Inject the import.\n\n    This needs to be created prior to knowing the catalog.\n    The profile itself is only needed for debug messages.\n    The import is one possibly several imports in that profile.\n    \"\"\"\n    self._import = import_\n    self._profile = profile\n    self._catalog_interface: Optional[CatalogInterface] = None\n    self._catalog: Optional[cat.Catalog] = None\n
                                    "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune.process","title":"process(self, catalog_iter)","text":"

                                    Prune the catalog based on the include rule in the import_.

                                    This only processes the one catalog yielded by the one import in this pipeline. It must yield in order to have the merge filter loop over available imported catalogs.

                                    Source code in trestle/core/resolver/prune.py
                                    def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n    Prune the catalog based on the include rule in the import_.\n\n    This only processes the one catalog yielded by the one import in this pipeline.\n    It must yield in order to have the merge filter loop over available imported catalogs.\n    \"\"\"\n    self._set_catalog(next(catalog_iter))\n    logger.debug(f'prune yielding catalog {self._catalog.metadata.title} with import {self._import.href}')\n    yield self._prune_catalog()\n
                                    "},{"location":"api_reference/trestle.core.rule_parameters_validator/","title":"rule_parameters_validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator","title":"trestle.core.rule_parameters_validator","text":"

                                    Validate by confirming rule parameter values are consistent.

                                    "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator","title":" RuleParametersValidator (Validator) ","text":"

                                    Validator to confirm all rule parameter values are consistent.

                                    Source code in trestle/core/rule_parameters_validator.py
                                    class RuleParametersValidator(Validator):\n\"\"\"Validator to confirm all rule parameter values are consistent.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize rule param values dictionary.\"\"\"\n        self._rule_param_values_dict: Dict[str, Any] = {}\n\n    def _add_imp_req_rule_params_to_dict(\n        self,\n        imp_requirement: ImplementedRequirement,\n        cat_int: CatalogInterface,\n    ) -> None:\n\"\"\"\n        Iterate all by components in an object and add the rule shared parameter values to list.\n\n        args:\n            imp_requirement: Current implemented requirement.\n            cat_int: Instance of catalog interface with controls catalog loaded.\n        \"\"\"\n        for by_component in as_list(imp_requirement.by_components):\n            # adds rule param values present in set parameters for current imp req\n            self._add_rule_params(imp_requirement, imp_requirement.control_id, cat_int, by_component.component_uuid)\n            # adds rule param values present in set parameters for current by_component in by_components list\n            # in the current implemented requirement\n            self._add_rule_params(by_component, imp_requirement.control_id, cat_int, by_component.component_uuid)\n            for statement in as_list(imp_requirement.statements):\n                # iterates by each by component inclded at each statemtent set for current imp req\n                for by_comp in as_list(statement.by_components):\n                    # adds rule param values present in set parameters for current by_component in by_components list\n                    # of current statement in current implemented requirement\n                    self._add_rule_params(by_comp, imp_requirement.control_id, cat_int, by_comp.component_uuid)\n\n    def _add_rule_params(\n        self, item: TypeWithSetParams, control_id: str, cat_int: CatalogInterface, comp_uuid: str = ''\n    ) -> None:\n\"\"\"\n        Add a rule shared parameter to the rule shared parameters list.\n\n        args:\n            item: Generic item to iterate over parameters.\n            control_id: Current control id.\n            cat_int: Instance of catalog interface with controls catalog loaded.\n            comp_uuid: Component uuid to save.\n        \"\"\"\n        for set_param in as_list(item.set_parameters):\n            # validates if current param_id is or not associated with a control so we can assume it\u00b4s a rule param\n            control = cat_int.get_control_by_param_id(set_param.param_id)\n            if not control:\n                deep_set(self._rule_param_values_dict, [set_param.param_id, comp_uuid, control_id], set_param.values)\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n            trestle_root: Trestle root path.\n\n        returns:\n            True (valid) if the model's rule parameter values are the same across controls.\n        \"\"\"\n        # verify if model type is either an SSP of a Component Definition\n        if not isinstance(model, SystemSecurityPlan):\n            return True\n\n        if not model.import_profile.href:\n            logger.info(f'INVALID: Model {model.metadata.title} has no referenced profile')\n            return False\n        profile_catalog = ProfileResolver().get_resolved_profile_catalog(trestle_root, model.import_profile.href)\n        catalog_interface = CatalogInterface(profile_catalog)\n        # iterate by each implemented requirement defined\n        for imp_req in model.control_implementation.implemented_requirements:\n            # adds rule param values to dict by implemented requirement basis\n            self._add_imp_req_rule_params_to_dict(imp_req, catalog_interface)\n        if self._rule_param_values_dict:\n            # compare all values in shared paramerets by component basis\n            for shared_param, values_dict in self._rule_param_values_dict.items():\n                for comp_name, value_dict in values_dict.items():\n                    expected_value = next(iter(value_dict.values()))\n                    if not all(value == expected_value for value in value_dict.values()):\n                        logger.error(\n                            f'Rule parameter values for param: {shared_param} in '\n                            f' {comp_name} are not consistent with '\n                            'other values provided across controls. Invalid model'\n                        )\n                        return False\n        return True\n
                                    "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator.__init__","title":"__init__(self) special","text":"

                                    Initialize rule param values dictionary.

                                    Source code in trestle/core/rule_parameters_validator.py
                                    def __init__(self) -> None:\n\"\"\"Initialize rule param values dictionary.\"\"\"\n    self._rule_param_values_dict: Dict[str, Any] = {}\n
                                    "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                    Test if the model is valid.

                                    Parameters:

                                    Name Type Description Default model ~TopLevelOscalModel

                                    A top level OSCAL model.

                                    required quiet bool

                                    Don't report msgs unless invalid.

                                    required trestle_root Optional[pathlib.Path]

                                    Trestle root path.

                                    None

                                    Returns:

                                    Type Description bool

                                    True (valid) if the model's rule parameter values are the same across controls.

                                    Source code in trestle/core/rule_parameters_validator.py
                                    def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n        trestle_root: Trestle root path.\n\n    returns:\n        True (valid) if the model's rule parameter values are the same across controls.\n    \"\"\"\n    # verify if model type is either an SSP of a Component Definition\n    if not isinstance(model, SystemSecurityPlan):\n        return True\n\n    if not model.import_profile.href:\n        logger.info(f'INVALID: Model {model.metadata.title} has no referenced profile')\n        return False\n    profile_catalog = ProfileResolver().get_resolved_profile_catalog(trestle_root, model.import_profile.href)\n    catalog_interface = CatalogInterface(profile_catalog)\n    # iterate by each implemented requirement defined\n    for imp_req in model.control_implementation.implemented_requirements:\n        # adds rule param values to dict by implemented requirement basis\n        self._add_imp_req_rule_params_to_dict(imp_req, catalog_interface)\n    if self._rule_param_values_dict:\n        # compare all values in shared paramerets by component basis\n        for shared_param, values_dict in self._rule_param_values_dict.items():\n            for comp_name, value_dict in values_dict.items():\n                expected_value = next(iter(value_dict.values()))\n                if not all(value == expected_value for value in value_dict.values()):\n                    logger.error(\n                        f'Rule parameter values for param: {shared_param} in '\n                        f' {comp_name} are not consistent with '\n                        'other values provided across controls. Invalid model'\n                    )\n                    return False\n    return True\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/","title":"ssp_io","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io","title":"trestle.core.ssp_io","text":"

                                    Handle direct IO for writing SSP responses as markdown.

                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter","title":" SSPMarkdownWriter ","text":"

                                    Class to write control responses as markdown.

                                    Functions in this class are mainly used by jinja and not by the trestle code itself.

                                    Source code in trestle/core/ssp_io.py
                                    class SSPMarkdownWriter():\n\"\"\"\n    Class to write control responses as markdown.\n\n    Functions in this class are mainly used by jinja and not by the trestle code itself.\n    \"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self._trestle_root = trestle_root\n        self._ssp: ssp.SystemSecurityPlan = None\n        self._resolved_catalog: Catalog = None\n        self._catalog_interface: CatalogInterface = None\n\n    def set_ssp(self, ssp: ssp.SystemSecurityPlan) -> None:\n\"\"\"Set ssp.\"\"\"\n        self._ssp = ssp\n\n    def set_catalog(self, resolved_catalog: Catalog) -> None:\n\"\"\"Set catalog.\"\"\"\n        self._resolved_catalog = resolved_catalog\n        self._catalog_interface = catalog_interface.CatalogInterface(self._resolved_catalog)\n\n    def get_control_statement(self, control_id: str, level: int) -> str:\n\"\"\"\n        Get the control statement for an ssp - to be printed in markdown as a structured list.\n\n        Args:\n            control_id: The control_id to use.\n\n        Returns:\n            A markdown blob as a string.\n        \"\"\"\n        if not self._resolved_catalog:\n            raise TrestleError('Cannot get control statement, set resolved catalog first.')\n\n        writer = DocsControlWriter()\n        control = self._catalog_interface.get_control(control_id)\n        if not control:\n            return ''\n\n        control_lines = writer.get_control_statement_ssp(control)\n\n        return self._build_tree_and_adjust(control_lines, level)\n\n    def get_control_part(self, control_id: str, part_name: str, level: int) -> str:\n\"\"\"Get control part with given name.\"\"\"\n        control_part = self._catalog_interface.get_control_part_prose(control_id, part_name)\n\n        md_list = self._write_str_with_header(\n            f'Control Part: {part_name} for control: {control_id}', control_part, level\n        )\n        return self._build_tree_and_adjust(md_list.split('\\n'), level)\n\n    def get_fedramp_control_tables(self, control_id: str, level: int, label_column: bool = False) -> str:\n\"\"\"Get the fedramp metadata as markdown tables, with optional third label column for params.\n\n        The fedramp metadata has the following elements:\n        - Responsible roles field\n        - Parameter values table\n        - Implementation status field\n        - Control origination field\n\n        Returns:\n            tables as one coherent markdown blob.\n        \"\"\"\n        resp_roles_table = self.get_responsible_roles_table(control_id, level)\n        params_values = self._parameter_table(control_id, level, label_column)\n        impl_status = self.get_fedramp_implementation_status(control_id, level)\n        control_orig = self.get_fedramp_control_origination(control_id, level)\n\n        final_output = ''\n        if resp_roles_table:\n            final_output += resp_roles_table\n        if params_values:\n            final_output += '\\n' + params_values\n        if impl_status:\n            final_output += '\\n' + impl_status\n        if control_orig:\n            final_output += '\\n' + control_orig\n        return final_output\n\n    def get_responsible_roles_table(self, control_id: str, level: int) -> str:\n\"\"\"\n        For each role id - if the role exists in metadata use the title as what gets printed in the roles table.\n\n        If not (for now) warn and use the role-id as the printed text.\n        \"\"\"\n        if self._ssp is None:\n            raise TrestleError('Cannot get responsible roles, SSP is not set.')\n\n        for impl_requirement in self._ssp.control_implementation.implemented_requirements:\n            if impl_requirement.control_id == control_id:\n                if impl_requirement.responsible_roles:\n                    resp_roles = as_list(impl_requirement.responsible_roles)\n                    role_ids = [role.role_id.replace('_', ' ') for role in resp_roles]\n\n                    # now check if this role exists in the metadata\n                    role_titles = dict(zip(role_ids, role_ids))\n                    roles = as_list(self._ssp.metadata.roles)\n                    for role in roles:\n                        if role.id in role_ids:\n                            role_titles[role.id] = role.title\n\n                    # dictionary to md table\n                    md_list = self._write_table_with_header(\n                        'Responsible Roles.', [[key, role_titles[key]] for key in role_titles.keys()],\n                        ['Role ID', 'Title'],\n                        level\n                    )\n                    return md_list\n                else:\n                    logger.warning(\n                        f'No responsible roles were found for the control with id: {control_id} in given SSP.'\n                    )\n                    return ''\n\n        return ''\n\n    def _parameter_table(self, control_id: str, level: int, label_column: bool = False) -> str:\n\"\"\"Print Param_id | ValueOrLabelOrChoices | Optional Label Column.\"\"\"\n        if not self._ssp:\n            raise TrestleError('Cannot get parameter table, set SSP first.')\n\n        writer = DocsControlWriter()\n        control = self._catalog_interface.get_control(control_id)\n        if not control:\n            return ''\n        params_lines = writer.get_param_table(control, label_column)\n        # need to make sure no params still have moustaches.  convert to brackets to avoid jinja complaints\n        clean_lines = []\n        for line in params_lines:\n            clean_lines.append(line.replace('{{', '[[').replace('}}', ']]'))\n\n        tree = DocsMarkdownNode.build_tree_from_markdown(clean_lines)\n        tree.change_header_level_by(level)\n        return tree.content.raw_text\n\n    def get_fedramp_implementation_status(self, control_id: str, level: int) -> str:\n\"\"\"\n        Print implementation status as a list of items, only showing those that are applicable for the control.\n\n        This is unlike the word document FedRAMP which uses checkboxes on standard set of options.\n        Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n        \"\"\"\n        if not self._ssp:\n            raise TrestleError('Cannot get Fedramp implementation status, set SSP first.')\n\n        implementation_statuses: List[str] = []\n        control_impl_req = self._control_implemented_req(control_id)\n        if control_impl_req and control_impl_req.props:\n            for prop in control_impl_req.props:\n                if prop.name == IMPLEMENTATION_STATUS:\n                    implementation_statuses.append(prop.value)\n\n        md_list = self._write_list_with_header('FedRamp Implementation Status.', implementation_statuses, level)\n        return md_list\n\n    def get_fedramp_control_origination(self, control_id: str, level: int) -> str:\n\"\"\"\n        Print control origination, as a list of items, only showing those that are applicable for the control.\n\n        Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n        \"\"\"\n        if not self._ssp:\n            raise TrestleError('Cannot get FedRamp control origination, set SSP first.')\n\n        control_origination = []\n        control_impl_req = self._control_implemented_req(control_id)\n\n        if control_impl_req and control_impl_req.props:\n            for prop in control_impl_req.props:\n                if prop.name == CONTROL_ORIGINATION:\n                    control_origination.append(prop.value)\n\n        md_list = self._write_list_with_header('FedRamp Control Origination.', control_origination, level)\n        return md_list\n\n    @staticmethod\n    def _write_component_prompt(\n        md_writer: MDWriter,\n        comp_name: str,\n        prose: str,\n        rules: List[str],\n        status: str,\n        show_rules: bool,\n        show_status: bool\n    ) -> None:\n        header = f'Component: {comp_name}'\n        md_writer.new_header(1, header)\n        md_writer.set_indent_level(-1)\n        md_writer.new_line(prose)\n        md_writer.set_indent_level(-1)\n        if rules and show_rules:\n            md_writer.new_header(2, title='Rules:')\n            md_writer.set_indent_level(-1)\n            md_writer.new_list(rules)\n            md_writer.set_indent_level(-1)\n        if status and show_status:\n            md_writer.new_header(2, title=f'Implementation Status: {status}')\n\n    def get_control_response(\n        self,\n        control_id: str,\n        level: int,\n        write_empty_responses: bool = False,\n        show_comp: bool = True,\n        show_rules: bool = False,\n        show_status: bool = True\n    ) -> str:\n\"\"\"\n        Get the full control implemented requirements, broken down based on the available control responses.\n\n        Args:\n            control_id: id of the control\n            level: level of indentation\n            write_empty_responses: write response even if empty\n            show_comp: show the component name in the response\n\n        Notes:\n            This is intended to be invoked from a jinja template that has already written out the prompt for\n            control response\n        \"\"\"\n        if not self._resolved_catalog:\n            raise TrestleError('Cannot get control response, set resolved catalog first.')\n\n        control = self._catalog_interface.get_control(control_id)\n        imp_req = self._control_implemented_req(control_id)\n        if not imp_req:\n            logger.info(f'No implemented requirements found for the control {control_id}')\n            return ''\n\n        md_writer = MDWriter(None)\n\n        system_prose = ''\n        system_rules = []\n        system_status = STATUS_OPERATIONAL\n        imp_req_responses = self._get_responses_by_components(imp_req, write_empty_responses)\n        if SSP_MAIN_COMP_NAME in imp_req_responses:\n            system_prose, system_rules, system_status = imp_req_responses[SSP_MAIN_COMP_NAME]\n\n        SSPMarkdownWriter._write_component_prompt(\n            md_writer, SSP_MAIN_COMP_NAME, system_prose, system_rules, system_status, show_rules, show_status\n        )\n\n        # if a control has no statement sub-parts then get the response bycomps from the imp_req itself\n        # otherwise get them from the statements in the imp_req\n        # an imp_req and a statement are both things that can have bycomps\n        has_bycomps = imp_req.statements if imp_req.statements else [imp_req]\n        for has_bycomp in has_bycomps:\n            statement_id = getattr(has_bycomp, 'statement_id', f'{control_id}_smt')\n            label = statement_id\n            part_name = None\n\n            # look up label for this statement\n            if control.parts:\n                found_label, part = self._catalog_interface.get_statement_label_if_exists(control_id, statement_id)\n                if found_label:\n                    label = found_label\n                    part_name = part.name\n\n            response_per_component = self._get_responses_by_components(has_bycomp, write_empty_responses)\n\n            if response_per_component or write_empty_responses:\n                if part_name and part_name == ITEM:\n                    # print part header only if subitem\n                    header = f'Implementation for part {label}'\n                    md_writer.new_header(1, title=header)\n                for comp_name, comp_response in response_per_component.items():\n                    if comp_name == SSP_MAIN_COMP_NAME:\n                        continue\n                    prose, rules, status = comp_response\n                    if show_comp:\n                        SSPMarkdownWriter._write_component_prompt(\n                            md_writer, comp_name, prose, rules, status, show_rules, show_status\n                        )\n\n        lines = md_writer.get_lines()\n\n        tree = DocsMarkdownNode.build_tree_from_markdown(lines)\n        tree.change_header_level_by(level)\n\n        return tree.content.raw_text\n\n    def _get_responses_by_components(self, has_bycomps: TypeWithByComps,\n                                     write_empty_responses: bool) -> Dict[str, Tuple[str, List[str], str]]:\n\"\"\"Get response per component, substitute component id with title if possible.\"\"\"\n        response_per_component: Dict[str, Tuple[str, str]] = {}\n        for by_comp in as_list(has_bycomps.by_components):  # type: ignore\n            # look up component title\n            subheader = by_comp.component_uuid\n            prose = ''\n            status = ''\n            rules = []\n            if self._ssp.system_implementation.components:\n                for comp in self._ssp.system_implementation.components:\n                    if comp.uuid == by_comp.component_uuid:\n                        title = comp.title\n                        if title:\n                            subheader = title\n            if by_comp.description:\n                prose = by_comp.description\n            if by_comp.implementation_status:\n                status = by_comp.implementation_status.state\n            rules, _ = ControlInterface.get_rule_list_for_item(by_comp)\n\n            if prose or (not prose and write_empty_responses):\n                if subheader:\n                    response_per_component[subheader] = (prose, rules, status)\n\n        return response_per_component\n\n    def _control_implemented_req(self, control_id: str) -> Optional[ssp.ImplementedRequirement]:\n\"\"\"Retrieve control implemented requirement by control-id.\"\"\"\n        requirements = self._ssp.control_implementation.implemented_requirements\n        for requirement in requirements:\n            if requirement.control_id == control_id:\n                return requirement\n        logger.debug(f'No implemented requirement found for control {control_id}')\n        return None\n\n    def _write_list_with_header(self, header: str, lines: List[str], level: int) -> str:\n        if lines:\n            md_writer = MDWriter(None)\n            md_writer.new_paragraph()\n            md_writer.new_header(level=1, title=header)\n            md_writer.set_indent_level(-1)\n            md_writer.new_list(lines)\n            md_writer.set_indent_level(-1)\n\n            return self._build_tree_and_adjust(md_writer.get_lines(), level)\n\n        return ''\n\n    def _write_table_with_header(\n        self, header: str, values: List[List[str]], table_header: List[str], level: int\n    ) -> str:\n        if values and values[0]:\n            md_writer = MDWriter(None)\n            md_writer.new_paragraph()\n            md_writer.new_header(level=1, title=header)\n            md_writer.set_indent_level(-1)\n            md_writer.new_table(values, table_header)\n            md_writer.set_indent_level(-1)\n\n            return self._build_tree_and_adjust(md_writer.get_lines(), level)\n        return ''\n\n    def _write_str_with_header(self, header: str, text: str, level: int) -> str:\n        if text:\n            md_writer = MDWriter(None)\n            md_writer.new_paragraph()\n            md_writer.new_header(level=1, title=header)\n            md_writer.set_indent_level(-1)\n            md_writer.new_line(text)\n            md_writer.set_indent_level(-1)\n\n            return self._build_tree_and_adjust(md_writer.get_lines(), level)\n        return ''\n\n    def _build_tree_and_adjust(self, lines: List[str], level: int) -> str:\n        tree = DocsMarkdownNode.build_tree_from_markdown(lines)\n        tree.change_header_level_by(level)\n\n        return tree.content.raw_text\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.__init__","title":"__init__(self, trestle_root) special","text":"

                                    Initialize the class.

                                    Source code in trestle/core/ssp_io.py
                                    def __init__(self, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self._trestle_root = trestle_root\n    self._ssp: ssp.SystemSecurityPlan = None\n    self._resolved_catalog: Catalog = None\n    self._catalog_interface: CatalogInterface = None\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_control_part","title":"get_control_part(self, control_id, part_name, level)","text":"

                                    Get control part with given name.

                                    Source code in trestle/core/ssp_io.py
                                    def get_control_part(self, control_id: str, part_name: str, level: int) -> str:\n\"\"\"Get control part with given name.\"\"\"\n    control_part = self._catalog_interface.get_control_part_prose(control_id, part_name)\n\n    md_list = self._write_str_with_header(\n        f'Control Part: {part_name} for control: {control_id}', control_part, level\n    )\n    return self._build_tree_and_adjust(md_list.split('\\n'), level)\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_control_response","title":"get_control_response(self, control_id, level, write_empty_responses=False, show_comp=True, show_rules=False, show_status=True)","text":"

                                    Get the full control implemented requirements, broken down based on the available control responses.

                                    Parameters:

                                    Name Type Description Default control_id str

                                    id of the control

                                    required level int

                                    level of indentation

                                    required write_empty_responses bool

                                    write response even if empty

                                    False show_comp bool

                                    show the component name in the response

                                    True

                                    Notes

                                    This is intended to be invoked from a jinja template that has already written out the prompt for control response

                                    Source code in trestle/core/ssp_io.py
                                    def get_control_response(\n    self,\n    control_id: str,\n    level: int,\n    write_empty_responses: bool = False,\n    show_comp: bool = True,\n    show_rules: bool = False,\n    show_status: bool = True\n) -> str:\n\"\"\"\n    Get the full control implemented requirements, broken down based on the available control responses.\n\n    Args:\n        control_id: id of the control\n        level: level of indentation\n        write_empty_responses: write response even if empty\n        show_comp: show the component name in the response\n\n    Notes:\n        This is intended to be invoked from a jinja template that has already written out the prompt for\n        control response\n    \"\"\"\n    if not self._resolved_catalog:\n        raise TrestleError('Cannot get control response, set resolved catalog first.')\n\n    control = self._catalog_interface.get_control(control_id)\n    imp_req = self._control_implemented_req(control_id)\n    if not imp_req:\n        logger.info(f'No implemented requirements found for the control {control_id}')\n        return ''\n\n    md_writer = MDWriter(None)\n\n    system_prose = ''\n    system_rules = []\n    system_status = STATUS_OPERATIONAL\n    imp_req_responses = self._get_responses_by_components(imp_req, write_empty_responses)\n    if SSP_MAIN_COMP_NAME in imp_req_responses:\n        system_prose, system_rules, system_status = imp_req_responses[SSP_MAIN_COMP_NAME]\n\n    SSPMarkdownWriter._write_component_prompt(\n        md_writer, SSP_MAIN_COMP_NAME, system_prose, system_rules, system_status, show_rules, show_status\n    )\n\n    # if a control has no statement sub-parts then get the response bycomps from the imp_req itself\n    # otherwise get them from the statements in the imp_req\n    # an imp_req and a statement are both things that can have bycomps\n    has_bycomps = imp_req.statements if imp_req.statements else [imp_req]\n    for has_bycomp in has_bycomps:\n        statement_id = getattr(has_bycomp, 'statement_id', f'{control_id}_smt')\n        label = statement_id\n        part_name = None\n\n        # look up label for this statement\n        if control.parts:\n            found_label, part = self._catalog_interface.get_statement_label_if_exists(control_id, statement_id)\n            if found_label:\n                label = found_label\n                part_name = part.name\n\n        response_per_component = self._get_responses_by_components(has_bycomp, write_empty_responses)\n\n        if response_per_component or write_empty_responses:\n            if part_name and part_name == ITEM:\n                # print part header only if subitem\n                header = f'Implementation for part {label}'\n                md_writer.new_header(1, title=header)\n            for comp_name, comp_response in response_per_component.items():\n                if comp_name == SSP_MAIN_COMP_NAME:\n                    continue\n                prose, rules, status = comp_response\n                if show_comp:\n                    SSPMarkdownWriter._write_component_prompt(\n                        md_writer, comp_name, prose, rules, status, show_rules, show_status\n                    )\n\n    lines = md_writer.get_lines()\n\n    tree = DocsMarkdownNode.build_tree_from_markdown(lines)\n    tree.change_header_level_by(level)\n\n    return tree.content.raw_text\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_control_statement","title":"get_control_statement(self, control_id, level)","text":"

                                    Get the control statement for an ssp - to be printed in markdown as a structured list.

                                    Parameters:

                                    Name Type Description Default control_id str

                                    The control_id to use.

                                    required

                                    Returns:

                                    Type Description str

                                    A markdown blob as a string.

                                    Source code in trestle/core/ssp_io.py
                                    def get_control_statement(self, control_id: str, level: int) -> str:\n\"\"\"\n    Get the control statement for an ssp - to be printed in markdown as a structured list.\n\n    Args:\n        control_id: The control_id to use.\n\n    Returns:\n        A markdown blob as a string.\n    \"\"\"\n    if not self._resolved_catalog:\n        raise TrestleError('Cannot get control statement, set resolved catalog first.')\n\n    writer = DocsControlWriter()\n    control = self._catalog_interface.get_control(control_id)\n    if not control:\n        return ''\n\n    control_lines = writer.get_control_statement_ssp(control)\n\n    return self._build_tree_and_adjust(control_lines, level)\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_fedramp_control_origination","title":"get_fedramp_control_origination(self, control_id, level)","text":"

                                    Print control origination, as a list of items, only showing those that are applicable for the control.

                                    Using a LUT to map between structured data fields, defined by FedRAMP and historical text.

                                    Source code in trestle/core/ssp_io.py
                                    def get_fedramp_control_origination(self, control_id: str, level: int) -> str:\n\"\"\"\n    Print control origination, as a list of items, only showing those that are applicable for the control.\n\n    Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n    \"\"\"\n    if not self._ssp:\n        raise TrestleError('Cannot get FedRamp control origination, set SSP first.')\n\n    control_origination = []\n    control_impl_req = self._control_implemented_req(control_id)\n\n    if control_impl_req and control_impl_req.props:\n        for prop in control_impl_req.props:\n            if prop.name == CONTROL_ORIGINATION:\n                control_origination.append(prop.value)\n\n    md_list = self._write_list_with_header('FedRamp Control Origination.', control_origination, level)\n    return md_list\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_fedramp_control_tables","title":"get_fedramp_control_tables(self, control_id, level, label_column=False)","text":"

                                    Get the fedramp metadata as markdown tables, with optional third label column for params.

                                    The fedramp metadata has the following elements: - Responsible roles field - Parameter values table - Implementation status field - Control origination field

                                    Returns:

                                    Type Description str

                                    tables as one coherent markdown blob.

                                    Source code in trestle/core/ssp_io.py
                                    def get_fedramp_control_tables(self, control_id: str, level: int, label_column: bool = False) -> str:\n\"\"\"Get the fedramp metadata as markdown tables, with optional third label column for params.\n\n    The fedramp metadata has the following elements:\n    - Responsible roles field\n    - Parameter values table\n    - Implementation status field\n    - Control origination field\n\n    Returns:\n        tables as one coherent markdown blob.\n    \"\"\"\n    resp_roles_table = self.get_responsible_roles_table(control_id, level)\n    params_values = self._parameter_table(control_id, level, label_column)\n    impl_status = self.get_fedramp_implementation_status(control_id, level)\n    control_orig = self.get_fedramp_control_origination(control_id, level)\n\n    final_output = ''\n    if resp_roles_table:\n        final_output += resp_roles_table\n    if params_values:\n        final_output += '\\n' + params_values\n    if impl_status:\n        final_output += '\\n' + impl_status\n    if control_orig:\n        final_output += '\\n' + control_orig\n    return final_output\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_fedramp_implementation_status","title":"get_fedramp_implementation_status(self, control_id, level)","text":"

                                    Print implementation status as a list of items, only showing those that are applicable for the control.

                                    This is unlike the word document FedRAMP which uses checkboxes on standard set of options. Using a LUT to map between structured data fields, defined by FedRAMP and historical text.

                                    Source code in trestle/core/ssp_io.py
                                    def get_fedramp_implementation_status(self, control_id: str, level: int) -> str:\n\"\"\"\n    Print implementation status as a list of items, only showing those that are applicable for the control.\n\n    This is unlike the word document FedRAMP which uses checkboxes on standard set of options.\n    Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n    \"\"\"\n    if not self._ssp:\n        raise TrestleError('Cannot get Fedramp implementation status, set SSP first.')\n\n    implementation_statuses: List[str] = []\n    control_impl_req = self._control_implemented_req(control_id)\n    if control_impl_req and control_impl_req.props:\n        for prop in control_impl_req.props:\n            if prop.name == IMPLEMENTATION_STATUS:\n                implementation_statuses.append(prop.value)\n\n    md_list = self._write_list_with_header('FedRamp Implementation Status.', implementation_statuses, level)\n    return md_list\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_responsible_roles_table","title":"get_responsible_roles_table(self, control_id, level)","text":"

                                    For each role id - if the role exists in metadata use the title as what gets printed in the roles table.

                                    If not (for now) warn and use the role-id as the printed text.

                                    Source code in trestle/core/ssp_io.py
                                    def get_responsible_roles_table(self, control_id: str, level: int) -> str:\n\"\"\"\n    For each role id - if the role exists in metadata use the title as what gets printed in the roles table.\n\n    If not (for now) warn and use the role-id as the printed text.\n    \"\"\"\n    if self._ssp is None:\n        raise TrestleError('Cannot get responsible roles, SSP is not set.')\n\n    for impl_requirement in self._ssp.control_implementation.implemented_requirements:\n        if impl_requirement.control_id == control_id:\n            if impl_requirement.responsible_roles:\n                resp_roles = as_list(impl_requirement.responsible_roles)\n                role_ids = [role.role_id.replace('_', ' ') for role in resp_roles]\n\n                # now check if this role exists in the metadata\n                role_titles = dict(zip(role_ids, role_ids))\n                roles = as_list(self._ssp.metadata.roles)\n                for role in roles:\n                    if role.id in role_ids:\n                        role_titles[role.id] = role.title\n\n                # dictionary to md table\n                md_list = self._write_table_with_header(\n                    'Responsible Roles.', [[key, role_titles[key]] for key in role_titles.keys()],\n                    ['Role ID', 'Title'],\n                    level\n                )\n                return md_list\n            else:\n                logger.warning(\n                    f'No responsible roles were found for the control with id: {control_id} in given SSP.'\n                )\n                return ''\n\n    return ''\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.set_catalog","title":"set_catalog(self, resolved_catalog)","text":"

                                    Set catalog.

                                    Source code in trestle/core/ssp_io.py
                                    def set_catalog(self, resolved_catalog: Catalog) -> None:\n\"\"\"Set catalog.\"\"\"\n    self._resolved_catalog = resolved_catalog\n    self._catalog_interface = catalog_interface.CatalogInterface(self._resolved_catalog)\n
                                    "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.set_ssp","title":"set_ssp(self, ssp)","text":"

                                    Set ssp.

                                    Source code in trestle/core/ssp_io.py
                                    def set_ssp(self, ssp: ssp.SystemSecurityPlan) -> None:\n\"\"\"Set ssp.\"\"\"\n    self._ssp = ssp\n
                                    "},{"location":"api_reference/trestle.core.trestle_base_model/","title":"trestle_base_model","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model","title":"trestle.core.trestle_base_model","text":"

                                    Trestle Base Model.

                                    "},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.Model","title":"Model","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel","title":" TrestleBaseModel (BaseModel) pydantic-model","text":"

                                    Trestle Base Model. Serves as wrapper around BaseModel for overriding methods.

                                    Source code in trestle/core/trestle_base_model.py
                                    class TrestleBaseModel(BaseModel):\n\"\"\"Trestle Base Model. Serves as wrapper around BaseModel for overriding methods.\"\"\"\n\n    @classmethod\n    def parse_obj(cls: Type['Model'], obj: Any) -> 'Model':\n\"\"\"Parse object to the given class.\"\"\"\n        try:\n            return super().parse_obj(obj)\n        except ValidationError as e:\n            # check if failed due to the wrong OSCAL version:\n            oscal_version_error = False\n            for err in e.errors():\n                for field in err['loc']:\n                    if field == 'oscal-version':\n                        message = err['msg']\n                        oscal_version_error = True\n                        break\n            if oscal_version_error:\n                raise TrestleError(f'{message}')\n            else:\n                raise\n
                                    "},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.parse_obj","title":"parse_obj(obj) classmethod","text":"

                                    Parse object to the given class.

                                    Source code in trestle/core/trestle_base_model.py
                                    @classmethod\ndef parse_obj(cls: Type['Model'], obj: Any) -> 'Model':\n\"\"\"Parse object to the given class.\"\"\"\n    try:\n        return super().parse_obj(obj)\n    except ValidationError as e:\n        # check if failed due to the wrong OSCAL version:\n        oscal_version_error = False\n        for err in e.errors():\n            for field in err['loc']:\n                if field == 'oscal-version':\n                    message = err['msg']\n                    oscal_version_error = True\n                    break\n        if oscal_version_error:\n            raise TrestleError(f'{message}')\n        else:\n            raise\n
                                    "},{"location":"api_reference/trestle.core.validator/","title":"validator","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator","title":"trestle.core.validator","text":"

                                    Base class for all validators.

                                    "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.validator/#trestle.core.validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator","title":" Validator (ABC) ","text":"

                                    Validator base class.

                                    Source code in trestle/core/validator.py
                                    class Validator(ABC):\n\"\"\"Validator base class.\"\"\"\n\n    def error_msg(self) -> Optional[str]:\n\"\"\"Error message used to describe this validator.\"\"\"\n        # subclasses can override as needed\n        return self.__doc__\n\n    @abstractmethod\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Validate the model.\n\n        args:\n            model: An Oscal model that can be passed to the validator.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            Whether or not the model passed this validation test.\n        \"\"\"\n\n    def validate(self, args: argparse.Namespace) -> int:\n\"\"\"Perform the validation according to user options.\"\"\"\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n\n        # validate by type - all of type or just specified by name\n        if args.type:\n            models = []\n            if args.name:\n                models = [args.name]\n            else:\n                models = ModelUtils.get_models_of_type(args.type, trestle_root)\n            models_path = trestle_root / ModelUtils.model_type_to_model_dir(args.type)\n            for m in models:\n                model_path = models_path / m\n                try:\n                    _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n                except TrestleError as e:\n                    logger.warning(f'File load error {e}')\n                    return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n                if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                    logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                    return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n                if not args.quiet:\n                    logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n            return CmdReturnCodes.SUCCESS.value\n\n        # validate all\n        if args.all:\n            model_tups = ModelUtils.get_all_models(trestle_root)\n            for mt in model_tups:\n\n                model_dir = trestle_root / ModelUtils.model_type_to_model_dir(mt[0]) / mt[1]\n                extension_type = trestle.common.file_utils.get_contextual_file_type(model_dir)\n                model_path = model_dir / f'{mt[0]}{FileContentType.to_file_extension(extension_type)}'\n                _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n                if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                    logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                    return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n                if not args.quiet:\n                    logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n            return CmdReturnCodes.SUCCESS.value\n\n        # validate file\n        if args.file:\n            file_path = trestle_root / args.file\n            _, _, model = ModelUtils.load_distributed(file_path, trestle_root)\n            if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                logger.info(f'INVALID: Model {file_path} did not pass the {self.error_msg()}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not args.quiet:\n                logger.info(f'VALID: Model {file_path} passed the {self.error_msg()}')\n        return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator.error_msg","title":"error_msg(self)","text":"

                                    Error message used to describe this validator.

                                    Source code in trestle/core/validator.py
                                    def error_msg(self) -> Optional[str]:\n\"\"\"Error message used to describe this validator.\"\"\"\n    # subclasses can override as needed\n    return self.__doc__\n
                                    "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                    Validate the model.

                                    Parameters:

                                    Name Type Description Default model ~TopLevelOscalModel

                                    An Oscal model that can be passed to the validator.

                                    required quiet bool

                                    Don't report msgs unless invalid.

                                    required

                                    Returns:

                                    Type Description bool

                                    Whether or not the model passed this validation test.

                                    Source code in trestle/core/validator.py
                                    @abstractmethod\ndef model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Validate the model.\n\n    args:\n        model: An Oscal model that can be passed to the validator.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        Whether or not the model passed this validation test.\n    \"\"\"\n
                                    "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator.validate","title":"validate(self, args)","text":"

                                    Perform the validation according to user options.

                                    Source code in trestle/core/validator.py
                                    def validate(self, args: argparse.Namespace) -> int:\n\"\"\"Perform the validation according to user options.\"\"\"\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n\n    # validate by type - all of type or just specified by name\n    if args.type:\n        models = []\n        if args.name:\n            models = [args.name]\n        else:\n            models = ModelUtils.get_models_of_type(args.type, trestle_root)\n        models_path = trestle_root / ModelUtils.model_type_to_model_dir(args.type)\n        for m in models:\n            model_path = models_path / m\n            try:\n                _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n            except TrestleError as e:\n                logger.warning(f'File load error {e}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not args.quiet:\n                logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n        return CmdReturnCodes.SUCCESS.value\n\n    # validate all\n    if args.all:\n        model_tups = ModelUtils.get_all_models(trestle_root)\n        for mt in model_tups:\n\n            model_dir = trestle_root / ModelUtils.model_type_to_model_dir(mt[0]) / mt[1]\n            extension_type = trestle.common.file_utils.get_contextual_file_type(model_dir)\n            model_path = model_dir / f'{mt[0]}{FileContentType.to_file_extension(extension_type)}'\n            _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n            if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not args.quiet:\n                logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n        return CmdReturnCodes.SUCCESS.value\n\n    # validate file\n    if args.file:\n        file_path = trestle_root / args.file\n        _, _, model = ModelUtils.load_distributed(file_path, trestle_root)\n        if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n            logger.info(f'INVALID: Model {file_path} did not pass the {self.error_msg()}')\n            return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n        if not args.quiet:\n            logger.info(f'VALID: Model {file_path} passed the {self.error_msg()}')\n    return CmdReturnCodes.SUCCESS.value\n
                                    "},{"location":"api_reference/trestle.core.validator_factory/","title":"validator_factory","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory","title":"trestle.core.validator_factory","text":"

                                    Register all validators here in the validator_factory.

                                    "},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory.validator_factory","title":"validator_factory: ObjectFactory","text":""},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory.init_arguments","title":"init_arguments(cmd)","text":"

                                    Feed the arguments to the argument parser.

                                    Source code in trestle/core/validator_factory.py
                                    def init_arguments(cmd: Command) -> None:\n\"\"\"Feed the arguments to the argument parser.\"\"\"\n    group = cmd.parser.add_mutually_exclusive_group(required=True)\n    group.add_argument('-f', '--file', help='Path of file in trestle directory to validate.')\n    group.add_argument('-t', '--type', choices=const.MODEL_TYPE_LIST, help='Validate one or all models of this type.')\n    group.add_argument('-a', '--all', action='store_true', help='Validate all models in trestle directory.')\n    cmd.add_argument('-n', '--name', help='Name of single model to validate (with --type specified).', required=False)\n    quiet_help = 'Do not report messages unless validation fails.'\n    cmd.add_argument('-q', '--quiet', action='store_true', help=quiet_help, required=False)\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/","title":"assessment_plan","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan","title":"trestle.oscal.assessment_plan","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan","title":" AssessmentPlan (OscalBaseModel) pydantic-model","text":"

                                    An assessment plan, such as those provided by a FedRAMP assessor.

                                    Source code in trestle/oscal/assessment_plan.py
                                    class AssessmentPlan(OscalBaseModel):\n\"\"\"\n    An assessment plan, such as those provided by a FedRAMP assessor.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment plan in this or other OSCAL instances. The locally defined UUID of the assessment plan can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Plan Universally Unique Identifier',\n    )\n    metadata: common.Metadata\n    import_ssp: common.ImportSsp = Field(..., alias='import-ssp')\n    local_definitions: Optional[LocalDefinitions] = Field(\n        None,\n        alias='local-definitions',\n        description=\n        'Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.',\n        title='Local Definitions'\n    )\n    terms_and_conditions: Optional[TermsAndConditions] = Field(\n        None,\n        alias='terms-and-conditions',\n        description=\n        'Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.',\n        title='Assessment Plan Terms and Conditions'\n    )\n    reviewed_controls: common.ReviewedControls = Field(..., alias='reviewed-controls')\n    assessment_subjects: Optional[List[common.AssessmentSubject]] = Field(None, alias='assessment-subjects')\n    assessment_assets: Optional[common.AssessmentAssets] = Field(None, alias='assessment-assets')\n    tasks: Optional[List[common.Task]] = Field(None)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.assessment_assets","title":"assessment_assets: AssessmentAssets pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.assessment_subjects","title":"assessment_subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.import_ssp","title":"import_ssp: ImportSsp pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.local_definitions","title":"local_definitions: LocalDefinitions pydantic-field","text":"

                                    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.reviewed_controls","title":"reviewed_controls: ReviewedControls pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.terms_and_conditions","title":"terms_and_conditions: TermsAndConditions pydantic-field","text":"

                                    Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.

                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment plan in this or other OSCAL instances. The locally defined UUID of the assessment plan can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_plan.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions","title":" LocalDefinitions (OscalBaseModel) pydantic-model","text":"

                                    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                    Source code in trestle/oscal/assessment_plan.py
                                    class LocalDefinitions(OscalBaseModel):\n\"\"\"\n    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[common.SystemComponent]] = Field(None)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    users: Optional[List[common.SystemUser]] = Field(None)\n    objectives_and_methods: Optional[List[common.LocalObjective]] = Field(None, alias='objectives-and-methods')\n    activities: Optional[List[common.Activity]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.activities","title":"activities: List[trestle.oscal.common.Activity] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.objectives_and_methods","title":"objectives_and_methods: List[trestle.oscal.common.LocalObjective] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.users","title":"users: List[trestle.oscal.common.SystemUser] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_plan.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/assessment_plan.py
                                    class Model(OscalBaseModel):\n    assessment_plan: AssessmentPlan = Field(..., alias='assessment-plan')\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.assessment_plan","title":"assessment_plan: AssessmentPlan pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions","title":" TermsAndConditions (OscalBaseModel) pydantic-model","text":"

                                    Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.

                                    Source code in trestle/oscal/assessment_plan.py
                                    class TermsAndConditions(OscalBaseModel):\n\"\"\"\n    Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    parts: Optional[List[common.AssessmentPart]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.parts","title":"parts: List[trestle.oscal.common.AssessmentPart] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_plan.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/","title":"assessment_results","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results","title":"trestle.oscal.assessment_results","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog","title":" AssessmentLog (OscalBaseModel) pydantic-model","text":"

                                    A log of all assessment-related actions taken.

                                    Source code in trestle/oscal/assessment_results.py
                                    class AssessmentLog(OscalBaseModel):\n\"\"\"\n    A log of all assessment-related actions taken.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    entries: List[Entry1] = Field(...)\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.entries","title":"entries: List[trestle.oscal.assessment_results.Entry1] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults","title":" AssessmentResults (OscalBaseModel) pydantic-model","text":"

                                    Security assessment results, such as those provided by a FedRAMP assessor in the FedRAMP Security Assessment Report.

                                    Source code in trestle/oscal/assessment_results.py
                                    class AssessmentResults(OscalBaseModel):\n\"\"\"\n    Security assessment results, such as those provided by a FedRAMP assessor in the FedRAMP Security Assessment Report.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment results instance in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Results Universally Unique Identifier',\n    )\n    metadata: common.Metadata\n    import_ap: ImportAp = Field(..., alias='import-ap')\n    local_definitions: Optional[LocalDefinitions] = Field(\n        None,\n        alias='local-definitions',\n        description=\n        'Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.',\n        title='Local Definitions'\n    )\n    results: List[Result] = Field(...)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.import_ap","title":"import_ap: ImportAp pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.local_definitions","title":"local_definitions: LocalDefinitions pydantic-field","text":"

                                    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.results","title":"results: List[trestle.oscal.assessment_results.Result] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment results instance in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation","title":" Attestation (OscalBaseModel) pydantic-model","text":"

                                    A set of textual statements, typically written by the assessor.

                                    Source code in trestle/oscal/assessment_results.py
                                    class Attestation(OscalBaseModel):\n\"\"\"\n    A set of textual statements, typically written by the assessor.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    responsible_parties: Optional[List[common.ResponsibleParty]] = Field(None, alias='responsible-parties')\n    parts: List[common.AssessmentPart] = Field(...)\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.parts","title":"parts: List[trestle.oscal.common.AssessmentPart] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1","title":" Entry1 (OscalBaseModel) pydantic-model","text":"

                                    Identifies the result of an action and/or task that occurred as part of executing an assessment plan or an assessment event that occurred in producing the assessment results.

                                    Source code in trestle/oscal/assessment_results.py
                                    class Entry1(OscalBaseModel):\n\"\"\"\n    Identifies the result of an action and/or task that occurred as part of executing an assessment plan or an assessment event that occurred in producing the assessment results.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference an assessment event in this or other OSCAL instances. The locally defined UUID of the assessment log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Log Entry Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this event.', title='Action Title')\n    description: Optional[str] = Field(\n        None, description='A human-readable description of this event.', title='Action Description'\n    )\n    start: datetime = Field(..., description='Identifies the start date and time of an event.', title='Start')\n    end: Optional[datetime] = Field(\n        None,\n        description=\n        'Identifies the end date and time of an event. If the event is a point in time, the start and end will be the same date and time.',\n        title='End'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    logged_by: Optional[List[common.LoggedBy]] = Field(None, alias='logged-by')\n    related_tasks: Optional[List[common.RelatedTask]] = Field(None, alias='related-tasks')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of this event.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.end","title":"end: datetime pydantic-field","text":"

                                    Identifies the end date and time of an event. If the event is a point in time, the start and end will be the same date and time.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.logged_by","title":"logged_by: List[trestle.oscal.common.LoggedBy] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.related_tasks","title":"related_tasks: List[trestle.oscal.common.RelatedTask] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.start","title":"start: datetime pydantic-field required","text":"

                                    Identifies the start date and time of an event.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.title","title":"title: str pydantic-field","text":"

                                    The title for this event.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference an assessment event in this or other OSCAL instances. The locally defined UUID of the assessment log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp","title":" ImportAp (OscalBaseModel) pydantic-model","text":"

                                    Used by assessment-results to import information about the original plan for assessing the system.

                                    Source code in trestle/oscal/assessment_results.py
                                    class ImportAp(OscalBaseModel):\n\"\"\"\n    Used by assessment-results to import information about the original plan for assessing the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description='A resolvable URL reference to the assessment plan governing the assessment activities.',\n        title='Assessment Plan Reference'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.href","title":"href: str pydantic-field required","text":"

                                    A resolvable URL reference to the assessment plan governing the assessment activities.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions","title":" LocalDefinitions (OscalBaseModel) pydantic-model","text":"

                                    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                    Source code in trestle/oscal/assessment_results.py
                                    class LocalDefinitions(OscalBaseModel):\n\"\"\"\n    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    objectives_and_methods: Optional[List[common.LocalObjective]] = Field(None, alias='objectives-and-methods')\n    activities: Optional[List[common.Activity]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.activities","title":"activities: List[trestle.oscal.common.Activity] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.objectives_and_methods","title":"objectives_and_methods: List[trestle.oscal.common.LocalObjective] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1","title":" LocalDefinitions1 (OscalBaseModel) pydantic-model","text":"

                                    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                    Source code in trestle/oscal/assessment_results.py
                                    class LocalDefinitions1(OscalBaseModel):\n\"\"\"\n    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[common.SystemComponent]] = Field(None)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    users: Optional[List[common.SystemUser]] = Field(None)\n    assessment_assets: Optional[common.AssessmentAssets] = Field(None, alias='assessment-assets')\n    tasks: Optional[List[common.Task]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.assessment_assets","title":"assessment_assets: AssessmentAssets pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.users","title":"users: List[trestle.oscal.common.SystemUser] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/assessment_results.py
                                    class Model(OscalBaseModel):\n    assessment_results: AssessmentResults = Field(..., alias='assessment-results')\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.assessment_results","title":"assessment_results: AssessmentResults pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result","title":" Result (OscalBaseModel) pydantic-model","text":"

                                    Used by the assessment results and POA&M. In the assessment results, this identifies all of the assessment observations and findings, initial and residual risks, deviations, and disposition. In the POA&M, this identifies initial and residual risks, deviations, and disposition.

                                    Source code in trestle/oscal/assessment_results.py
                                    class Result(OscalBaseModel):\n\"\"\"\n    Used by the assessment results and POA&M. In the assessment results, this identifies all of the assessment observations and findings, initial and residual risks, deviations, and disposition. In the POA&M, this identifies initial and residual risks, deviations, and disposition.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this set of results in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Results Universally Unique Identifier',\n    )\n    title: str = Field(..., description='The title for this set of results.', title='Results Title')\n    description: str = Field(\n        ..., description='A human-readable description of this set of test results.', title='Results Description'\n    )\n    start: datetime = Field(\n        ...,\n        description='Date/time stamp identifying the start of the evidence collection reflected in these results.',\n        title='start field'\n    )\n    end: Optional[datetime] = Field(\n        None,\n        description=\n        'Date/time stamp identifying the end of the evidence collection reflected in these results. In a continuous motoring scenario, this may contain the same value as start if appropriate.',\n        title='end field'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    local_definitions: Optional[LocalDefinitions1] = Field(\n        None,\n        alias='local-definitions',\n        description=\n        'Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.',\n        title='Local Definitions'\n    )\n    reviewed_controls: common.ReviewedControls = Field(..., alias='reviewed-controls')\n    attestations: Optional[List[Attestation]] = Field(None)\n    assessment_log: Optional[AssessmentLog] = Field(\n        None,\n        alias='assessment-log',\n        description='A log of all assessment-related actions taken.',\n        title='Assessment Log'\n    )\n    observations: Optional[List[common.Observation]] = Field(None)\n    risks: Optional[List[common.Risk]] = Field(None)\n    findings: Optional[List[common.Finding]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.assessment_log","title":"assessment_log: AssessmentLog pydantic-field","text":"

                                    A log of all assessment-related actions taken.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.attestations","title":"attestations: List[trestle.oscal.assessment_results.Attestation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this set of test results.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.end","title":"end: datetime pydantic-field","text":"

                                    Date/time stamp identifying the end of the evidence collection reflected in these results. In a continuous motoring scenario, this may contain the same value as start if appropriate.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.findings","title":"findings: List[trestle.oscal.common.Finding] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.local_definitions","title":"local_definitions: LocalDefinitions1 pydantic-field","text":"

                                    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.observations","title":"observations: List[trestle.oscal.common.Observation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.reviewed_controls","title":"reviewed_controls: ReviewedControls pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.risks","title":"risks: List[trestle.oscal.common.Risk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.start","title":"start: datetime pydantic-field required","text":"

                                    Date/time stamp identifying the start of the evidence collection reflected in these results.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.title","title":"title: str pydantic-field required","text":"

                                    The title for this set of results.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this set of results in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/","title":"catalog","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog","title":"trestle.oscal.catalog","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog","title":" Catalog (OscalBaseModel) pydantic-model","text":"

                                    A structured, organized collection of control information.

                                    Source code in trestle/oscal/catalog.py
                                    class Catalog(OscalBaseModel):\n\"\"\"\n    A structured, organized collection of control information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given catalog instance.',\n                     title='Catalog Universally Unique Identifier'\n                 )\n    metadata: common.Metadata\n    params: Optional[List[common.Parameter]] = Field(None)\n    controls: Optional[List[Control]] = Field(None)\n    groups: Optional[List[Group]] = Field(None)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.controls","title":"controls: List[trestle.oscal.catalog.Control] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.groups","title":"groups: List[trestle.oscal.catalog.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    Provides a globally unique means to identify a given catalog instance.

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.Config","title":" Config ","text":"Source code in trestle/oscal/catalog.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control","title":" Control (OscalBaseModel) pydantic-model","text":"

                                    A structured object representing a requirement or guideline, which when implemented will reduce an aspect of risk related to an information system and its information.

                                    Source code in trestle/oscal/catalog.py
                                    class Control(OscalBaseModel):\n\"\"\"\n    A structured object representing a requirement or guideline, which when implemented will reduce an aspect of risk related to an information system and its information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        'Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles).',\n        title='Control Identifier'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a sub-type or characterization of the control.',\n        title='Control Class'\n    )\n    title: str = Field(\n        ...,\n        description='A name given to the control, which may be used by a tool for display and navigation.',\n        title='Control Title'\n    )\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n    controls: Optional[List[Control]] = None\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    A textual label that provides a sub-type or characterization of the control.

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.controls","title":"controls: List[trestle.oscal.catalog.Control] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.id","title":"id: ConstrainedStrValue pydantic-field required","text":"

                                    Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles).

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.title","title":"title: str pydantic-field required","text":"

                                    A name given to the control, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.Config","title":" Config ","text":"Source code in trestle/oscal/catalog.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group","title":" Group (OscalBaseModel) pydantic-model","text":"

                                    A group of controls, or of groups of controls.

                                    Source code in trestle/oscal/catalog.py
                                    class Group(OscalBaseModel):\n\"\"\"\n    A group of controls, or of groups of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        description=\n        'Identifies the group for the purpose of cross-linking within the defining instance or from other instances that reference the catalog.',\n        title='Group Identifier'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a sub-type or characterization of the group.',\n        title='Group Class'\n    )\n    title: str = Field(\n        ...,\n        description='A name given to the group, which may be used by a tool for display and navigation.',\n        title='Group Title'\n    )\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n    groups: Optional[List[Group]] = None\n    controls: Optional[List[Control]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    A textual label that provides a sub-type or characterization of the group.

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.controls","title":"controls: List[trestle.oscal.catalog.Control] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.groups","title":"groups: List[trestle.oscal.catalog.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.id","title":"id: ConstrainedStrValue pydantic-field","text":"

                                    Identifies the group for the purpose of cross-linking within the defining instance or from other instances that reference the catalog.

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.title","title":"title: str pydantic-field required","text":"

                                    A name given to the group, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.Config","title":" Config ","text":"Source code in trestle/oscal/catalog.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/catalog.py
                                    class Model(OscalBaseModel):\n    catalog: Catalog\n
                                    "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.catalog","title":"catalog: Catalog pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/","title":"common","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common","title":"trestle.oscal.common","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action","title":" Action (OscalBaseModel) pydantic-model","text":"

                                    An action applied by a role within a given party to the content.

                                    Source code in trestle/oscal/common.py
                                    class Action(OscalBaseModel):\n\"\"\"\n    An action applied by a role within a given party to the content.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A unique identifier that can be used to reference this defined action elsewhere in an OSCAL document. A UUID should be consistently used for a given location across revisions of the document.',\n        title='Action Universally Unique Identifier'\n    )\n    date: Optional[datetime] = Field(\n        None, description='The date and time when the action occurred.', title='Action Occurrence Date'\n    )\n    type: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ..., description='The type of action documented by the assembly, such as an approval.', title='Action Type'\n    )\n    system: AnyUrl = Field(..., description='Specifies the action type system used.', title='Action Type System')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.date","title":"date: datetime pydantic-field","text":"

                                    The date and time when the action occurred.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.system","title":"system: AnyUrl pydantic-field required","text":"

                                    Specifies the action type system used.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.type","title":"type: ConstrainedStrValue pydantic-field required","text":"

                                    The type of action documented by the assembly, such as an approval.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A unique identifier that can be used to reference this defined action elsewhere in an OSCAL document. A UUID should be consistently used for a given location across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity","title":" Activity (OscalBaseModel) pydantic-model","text":"

                                    Identifies an assessment or related process that can be performed. In the assessment plan, this is an intended activity which may be associated with an assessment task. In the assessment results, this an activity that was actually performed as part of an assessment.

                                    Source code in trestle/oscal/common.py
                                    class Activity(OscalBaseModel):\n\"\"\"\n    Identifies an assessment or related process that can be performed. In the assessment plan, this is an intended activity which may be associated with an assessment task. In the assessment results, this an activity that was actually performed as part of an assessment.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment activity elsewhere in this or other OSCAL instances. The locally defined UUID of the activity can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Activity Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(\n        None, description='The title for this included activity.', title='Included Activity Title'\n    )\n    description: str = Field(\n        ...,\n        description='A human-readable description of this included activity.',\n        title='Included Activity Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    steps: Optional[List[Step]] = Field(None)\n    related_controls: Optional[ReviewedControls] = Field(None, alias='related-controls')\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this included activity.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.related_controls","title":"related_controls: ReviewedControls pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.steps","title":"steps: List[trestle.oscal.common.Step] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.title","title":"title: str pydantic-field","text":"

                                    The title for this included activity.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment activity elsewhere in this or other OSCAL instances. The locally defined UUID of the activity can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine","title":" AddrLine (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class AddrLine(OscalBaseModel):\n    __root__: StringDatatype = Field(..., description='A single line of an address.', title='Address line')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                    A single line of an address.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address","title":" Address (OscalBaseModel) pydantic-model","text":"

                                    A postal address for the location.

                                    Source code in trestle/oscal/common.py
                                    class Address(OscalBaseModel):\n\"\"\"\n    A postal address for the location.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: Optional[Union[TokenDatatype, AddressTypeValidValues]] = Field(\n        None, description='Indicates the type of address.', title='Address Type'\n    )\n    addr_lines: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None, alias='addr-lines')\n    city: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='City, town or geographical region for the mailing address.', title='City'\n    )\n    state: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='State, province or analogous geographical region for a mailing address.', title='State'\n    )\n    postal_code: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, alias='postal-code', description='Postal or ZIP code for mailing address.', title='Postal Code'\n    )\n    country: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='The ISO 3166-1 alpha-2 country code for the mailing address.', title='Country Code'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.addr_lines","title":"addr_lines: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.city","title":"city: ConstrainedStrValue pydantic-field","text":"

                                    City, town or geographical region for the mailing address.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.country","title":"country: ConstrainedStrValue pydantic-field","text":"

                                    The ISO 3166-1 alpha-2 country code for the mailing address.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.postal_code","title":"postal_code: ConstrainedStrValue pydantic-field","text":"

                                    Postal or ZIP code for mailing address.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.state","title":"state: ConstrainedStrValue pydantic-field","text":"

                                    State, province or analogous geographical region for a mailing address.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.AddressTypeValidValues] pydantic-field","text":"

                                    Indicates the type of address.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddressTypeValidValues","title":" AddressTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class AddressTypeValidValues(Enum):\n    home = 'home'\n    work = 'work'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddressTypeValidValues.home","title":"home","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddressTypeValidValues.work","title":"work","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm","title":" Algorithm (Enum) ","text":"

                                    The digest method by which a hash is derived.

                                    Source code in trestle/oscal/common.py
                                    class Algorithm(Enum):\n\"\"\"\n    The digest method by which a hash is derived.\n    \"\"\"\n\n    SHA_224 = 'SHA-224'\n    SHA_256 = 'SHA-256'\n    SHA_384 = 'SHA-384'\n    SHA_512 = 'SHA-512'\n    SHA3_224 = 'SHA3-224'\n    SHA3_256 = 'SHA3-256'\n    SHA3_384 = 'SHA3-384'\n    SHA3_512 = 'SHA3-512'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_224","title":"SHA3_224","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_256","title":"SHA3_256","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_384","title":"SHA3_384","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_512","title":"SHA3_512","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_224","title":"SHA_224","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_256","title":"SHA_256","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_384","title":"SHA_384","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_512","title":"SHA_512","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets","title":" AssessmentAssets (OscalBaseModel) pydantic-model","text":"

                                    Identifies the assets used to perform this assessment, such as the assessment team, scanning tools, and assumptions.

                                    Source code in trestle/oscal/common.py
                                    class AssessmentAssets(OscalBaseModel):\n\"\"\"\n    Identifies the assets used to perform this assessment, such as the assessment team, scanning tools, and assumptions.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[SystemComponent]] = Field(None)\n    assessment_platforms: List[AssessmentPlatform] = Field(..., alias='assessment-platforms')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.assessment_platforms","title":"assessment_platforms: List[trestle.oscal.common.AssessmentPlatform] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart","title":" AssessmentPart (OscalBaseModel) pydantic-model","text":"

                                    A partition of an assessment plan or results or a child of another part.

                                    Source code in trestle/oscal/common.py
                                    class AssessmentPart(OscalBaseModel):\n\"\"\"\n    A partition of an assessment plan or results or a child of another part.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this part elsewhere in this or other OSCAL instances. The locally defined UUID of the part can be used to reference the data item locally or globally (e.g., in an ported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Part Identifier'\n    )\n    name: Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                Name] = Field(\n                    ...,\n                    description=\"A textual label that uniquely identifies the part's semantic type.\",\n                    title='Part Name'\n                )\n    ns: Optional[AnyUrl] = Field(\n        None,\n        description=\n        \"A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.\",\n        title='Part Namespace'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\n        \"A textual label that provides a sub-type or characterization of the part's name. This can be used to further distinguish or discriminate between the semantics of multiple parts of the same control with the same name and ns.\",\n        title='Part Class'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the part, which may be used by a tool for display and navigation.',\n        title='Part Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    prose: Optional[str] = Field(None, description='Permits multiple paragraphs, lists, tables etc.', title='Part Text')\n    parts: Optional[List[AssessmentPart]] = None\n    links: Optional[List[Link]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    A textual label that provides a sub-type or characterization of the part's name. This can be used to further distinguish or discriminate between the semantics of multiple parts of the same control with the same name and ns.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.name","title":"name: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Name] pydantic-field required","text":"

                                    A textual label that uniquely identifies the part's semantic type.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.ns","title":"ns: AnyUrl pydantic-field","text":"

                                    A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.parts","title":"parts: List[trestle.oscal.common.AssessmentPart] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.prose","title":"prose: str pydantic-field","text":"

                                    Permits multiple paragraphs, lists, tables etc.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.title","title":"title: str pydantic-field","text":"

                                    A name given to the part, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this part elsewhere in this or other OSCAL instances. The locally defined UUID of the part can be used to reference the data item locally or globally (e.g., in an ported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform","title":" AssessmentPlatform (OscalBaseModel) pydantic-model","text":"

                                    Used to represent the toolset used to perform aspects of the assessment.

                                    Source code in trestle/oscal/common.py
                                    class AssessmentPlatform(OscalBaseModel):\n\"\"\"\n    Used to represent the toolset used to perform aspects of the assessment.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment platform elsewhere in this or other OSCAL instances. The locally defined UUID of the assessment platform can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Platform Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(\n        None, description='The title or name for the assessment platform.', title='Assessment Platform Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    uses_components: Optional[List[UsesComponent]] = Field(None, alias='uses-components')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.title","title":"title: str pydantic-field","text":"

                                    The title or name for the assessment platform.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.uses_components","title":"uses_components: List[trestle.oscal.common.UsesComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment platform elsewhere in this or other OSCAL instances. The locally defined UUID of the assessment platform can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject","title":" AssessmentSubject (OscalBaseModel) pydantic-model","text":"

                                    Identifies system elements being assessed, such as components, inventory items, and locations. In the assessment plan, this identifies a planned assessment subject. In the assessment results this is an actual assessment subject, and reflects any changes from the plan. exactly what will be the focus of this assessment. Any subjects not identified in this way are out-of-scope.

                                    Source code in trestle/oscal/common.py
                                    class AssessmentSubject(OscalBaseModel):\n\"\"\"\n    Identifies system elements being assessed, such as components, inventory items, and locations. In the assessment plan, this identifies a planned assessment subject. In the assessment results this is an actual assessment subject, and reflects any changes from the plan. exactly what will be the focus of this assessment. Any subjects not identified in this way are out-of-scope.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: Union[TokenDatatype, AssessmentSubjectValidValues] = Field(\n        ...,\n        description=\n        'Indicates the type of assessment subject, such as a component, inventory, item, location, or party represented by this selection statement.',\n        title='Subject Type'\n    )\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of the collection of subjects being included in this assessment.',\n        title='Include Subjects Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    include_all: Optional[IncludeAll] = Field(None, alias='include-all')\n    include_subjects: Optional[List[SelectSubjectById]] = Field(None, alias='include-subjects')\n    exclude_subjects: Optional[List[SelectSubjectById]] = Field(None, alias='exclude-subjects')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of the collection of subjects being included in this assessment.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.exclude_subjects","title":"exclude_subjects: List[trestle.oscal.common.SelectSubjectById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.include_subjects","title":"include_subjects: List[trestle.oscal.common.SelectSubjectById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.AssessmentSubjectValidValues] pydantic-field required","text":"

                                    Indicates the type of assessment subject, such as a component, inventory, item, location, or party represented by this selection statement.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder","title":" AssessmentSubjectPlaceholder (OscalBaseModel) pydantic-model","text":"

                                    Used when the assessment subjects will be determined as part of one or more other assessment activities. These assessment subjects will be recorded in the assessment results in the assessment log.

                                    Source code in trestle/oscal/common.py
                                    class AssessmentSubjectPlaceholder(OscalBaseModel):\n\"\"\"\n    Used when the assessment subjects will be determined as part of one or more other assessment activities. These assessment subjects will be recorded in the assessment results in the assessment log.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier for a set of assessment subjects that will be identified by a task or an activity that is part of a task. The locally defined UUID of the assessment subject placeholder can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Subject Placeholder Universally Unique Identifier',\n    )\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of intent of this assessment subject placeholder.',\n        title='Assessment Subject Placeholder Description'\n    )\n    sources: List[Source] = Field(...)\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of intent of this assessment subject placeholder.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.sources","title":"sources: List[trestle.oscal.common.Source] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier for a set of assessment subjects that will be identified by a task or an activity that is part of a task. The locally defined UUID of the assessment subject placeholder can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues","title":" AssessmentSubjectValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class AssessmentSubjectValidValues(Enum):\n    component = 'component'\n    inventory_item = 'inventory-item'\n    location = 'location'\n    party = 'party'\n    user = 'user'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.component","title":"component","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.inventory_item","title":"inventory_item","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.location","title":"location","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.user","title":"user","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity","title":" AssociatedActivity (OscalBaseModel) pydantic-model","text":"

                                    Identifies an individual activity to be performed as part of a task.

                                    Source code in trestle/oscal/common.py
                                    class AssociatedActivity(OscalBaseModel):\n\"\"\"\n    Identifies an individual activity to be performed as part of a task.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    activity_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='activity-uuid',\n        description='A machine-oriented identifier reference to an activity defined in the list of activities.',\n        title='Activity Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    subjects: List[AssessmentSubject] = Field(...)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.activity_uuid","title":"activity_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to an activity defined in the list of activities.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency","title":" AtFrequency (OscalBaseModel) pydantic-model","text":"

                                    The task is intended to occur at the specified frequency.

                                    Source code in trestle/oscal/common.py
                                    class AtFrequency(OscalBaseModel):\n\"\"\"\n    The task is intended to occur at the specified frequency.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    period: conint(\n        ge=1, multiple_of=1\n    ) = Field(..., description='The task must occur after the specified period has elapsed.', title='Period')\n    unit: TimeUnitValidValues = Field(..., description='The unit of time for the period.', title='Time Unit')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.period","title":"period: ConstrainedIntValue pydantic-field required","text":"

                                    The task must occur after the specified period has elapsed.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.unit","title":"unit: TimeUnitValidValues pydantic-field required","text":"

                                    The unit of time for the period.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege","title":" AuthorizedPrivilege (OscalBaseModel) pydantic-model","text":"

                                    Identifies a specific system privilege held by the user, along with an associated description and/or rationale for the privilege.

                                    Source code in trestle/oscal/common.py
                                    class AuthorizedPrivilege(OscalBaseModel):\n\"\"\"\n    Identifies a specific system privilege held by the user, along with an associated description and/or rationale for the privilege.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    title: str = Field(..., description='A human readable name for the privilege.', title='Privilege Title')\n    description: Optional[str] = Field(\n        None, description=\"A summary of the privilege's purpose within the system.\", title='Privilege Description'\n    )\n    functions_performed: List[constr(regex=r'^\\S(.*\\S)?$')] = Field(..., alias='functions-performed')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.description","title":"description: str pydantic-field","text":"

                                    A summary of the privilege's purpose within the system.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.functions_performed","title":"functions_performed: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.title","title":"title: str pydantic-field required","text":"

                                    A human readable name for the privilege.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter","title":" BackMatter (OscalBaseModel) pydantic-model","text":"

                                    A collection of resources that may be referenced from within the OSCAL document instance.

                                    Source code in trestle/oscal/common.py
                                    class BackMatter(OscalBaseModel):\n\"\"\"\n    A collection of resources that may be referenced from within the OSCAL document instance.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    resources: Optional[List[Resource]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.resources","title":"resources: List[trestle.oscal.common.Resource] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64","title":" Base64 (OscalBaseModel) pydantic-model","text":"

                                    A resource encoded using the Base64 alphabet defined by RFC 2045.

                                    Source code in trestle/oscal/common.py
                                    class Base64(OscalBaseModel):\n\"\"\"\n    A resource encoded using the Base64 alphabet defined by RFC 2045.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    filename: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        description=\n        'Name of the file before it was encoded as Base64 to be embedded in a resource. This is the name that will be assigned to the file when the file is decoded.',\n        title='File Name'\n    )\n    media_type: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='media-type',\n        description='A label that indicates the nature of a resource, as a data serialization or format.',\n        title='Media Type'\n    )\n    value: constr(regex=r'^[0-9A-Za-z+/]+={0,2}$')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.filename","title":"filename: ConstrainedStrValue pydantic-field","text":"

                                    Name of the file before it was encoded as Base64 to be embedded in a resource. This is the name that will be assigned to the file when the file is decoded.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.media_type","title":"media_type: ConstrainedStrValue pydantic-field","text":"

                                    A label that indicates the nature of a resource, as a data serialization or format.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.value","title":"value: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype","title":" Base64Datatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class Base64Datatype(OscalBaseModel):\n    __root__: constr(\n        regex=r'^[0-9A-Za-z+/]+={0,2}$'\n    ) = Field(..., description='Binary data encoded using the Base 64 encoding algorithm as defined by RFC4648.')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    Binary data encoded using the Base 64 encoding algorithm as defined by RFC4648.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization","title":" Characterization (OscalBaseModel) pydantic-model","text":"

                                    A collection of descriptive data about the containing object from a specific origin.

                                    Source code in trestle/oscal/common.py
                                    class Characterization(OscalBaseModel):\n\"\"\"\n    A collection of descriptive data about the containing object from a specific origin.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    origin: Origin\n    facets: List[Facet] = Field(...)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.facets","title":"facets: List[trestle.oscal.common.Facet] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.origin","title":"origin: Origin pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation","title":" Citation (OscalBaseModel) pydantic-model","text":"

                                    An optional citation consisting of end note text using structured markup.

                                    Source code in trestle/oscal/common.py
                                    class Citation(OscalBaseModel):\n\"\"\"\n    An optional citation consisting of end note text using structured markup.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    text: str = Field(..., description='A line of citation text.', title='Citation Text')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.text","title":"text: str pydantic-field required","text":"

                                    A line of citation text.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection","title":" ControlObjectiveSelection (OscalBaseModel) pydantic-model","text":"

                                    Identifies the control objectives of the assessment. In the assessment plan, these are the planned objectives. In the assessment results, these are the assessed objectives, and reflects any changes from the plan.

                                    Source code in trestle/oscal/common.py
                                    class ControlObjectiveSelection(OscalBaseModel):\n\"\"\"\n    Identifies the control objectives of the assessment. In the assessment plan, these are the planned objectives. In the assessment results, these are the assessed objectives, and reflects any changes from the plan.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of this collection of control objectives.',\n        title='Control Objectives Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    include_all: Optional[IncludeAll] = Field(None, alias='include-all')\n    include_objectives: Optional[List[SelectObjectiveById]] = Field(None, alias='include-objectives')\n    exclude_objectives: Optional[List[SelectObjectiveById]] = Field(None, alias='exclude-objectives')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of this collection of control objectives.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.exclude_objectives","title":"exclude_objectives: List[trestle.oscal.common.SelectObjectiveById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.include_objectives","title":"include_objectives: List[trestle.oscal.common.SelectObjectiveById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection","title":" ControlSelection (OscalBaseModel) pydantic-model","text":"

                                    Identifies the controls being assessed. In the assessment plan, these are the planned controls. In the assessment results, these are the actual controls, and reflects any changes from the plan.

                                    Source code in trestle/oscal/common.py
                                    class ControlSelection(OscalBaseModel):\n\"\"\"\n    Identifies the controls being assessed. In the assessment plan, these are the planned controls. In the assessment results, these are the actual controls, and reflects any changes from the plan.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of in-scope controls specified for assessment.',\n        title='Assessed Controls Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    include_all: Optional[IncludeAll] = Field(None, alias='include-all')\n    include_controls: Optional[List[SelectControlById]] = Field(None, alias='include-controls')\n    exclude_controls: Optional[List[SelectControlById]] = Field(None, alias='exclude-controls')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of in-scope controls specified for assessment.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.exclude_controls","title":"exclude_controls: List[trestle.oscal.common.SelectControlById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.include_controls","title":"include_controls: List[trestle.oscal.common.SelectControlById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype","title":" DateTimeWithTimezoneDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class DateTimeWithTimezoneDatatype(OscalBaseModel):\n    __root__: datetime = Field(..., description='A string representing a point in time with a required timezone.')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__root__","title":"__root__: datetime pydantic-field required special","text":"

                                    A string representing a point in time with a required timezone.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency","title":" Dependency (OscalBaseModel) pydantic-model","text":"

                                    Used to indicate that a task is dependent on another task.

                                    Source code in trestle/oscal/common.py
                                    class Dependency(OscalBaseModel):\n\"\"\"\n    Used to indicate that a task is dependent on another task.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    task_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='task-uuid',\n        description='A machine-oriented identifier reference to a unique task.',\n        title='Task Universally Unique Identifier Reference'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.task_uuid","title":"task_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a unique task.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId","title":" DocumentId (OscalBaseModel) pydantic-model","text":"

                                    A document identifier qualified by an identifier scheme.

                                    Source code in trestle/oscal/common.py
                                    class DocumentId(OscalBaseModel):\n\"\"\"\n    A document identifier qualified by an identifier scheme.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    scheme: Optional[Union[URIDatatype, DocumentSchemeValidValues]] = Field(\n        None,\n        description=\n        'Qualifies the kind of document identifier using a URI. If the scheme is not provided the value of the element will be interpreted as a string of characters.',\n        title='Document Identification Scheme'\n    )\n    identifier: constr(regex=r'^\\S(.*\\S)?$')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.identifier","title":"identifier: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.scheme","title":"scheme: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.DocumentSchemeValidValues] pydantic-field","text":"

                                    Qualifies the kind of document identifier using a URI. If the scheme is not provided the value of the element will be interpreted as a string of characters.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentSchemeValidValues","title":" DocumentSchemeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class DocumentSchemeValidValues(Enum):\n    http___www_doi_org_ = 'http://www.doi.org/'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress","title":" EmailAddress (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class EmailAddress(OscalBaseModel):\n    __root__: EmailStr = Field(\n        ..., description='An email address as defined by RFC 5322 Section 3.4.1.', title='Email Address'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__root__","title":"__root__: EmailStr pydantic-field required special","text":"

                                    An email address as defined by RFC 5322 Section 3.4.1.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype","title":" EmailAddressDatatype (OscalBaseModel) pydantic-model","text":"

                                    An email address string formatted according to RFC 6531.

                                    Source code in trestle/oscal/common.py
                                    class EmailAddressDatatype(OscalBaseModel):\n\"\"\"\n    An email address string formatted according to RFC 6531.\n    \"\"\"\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry","title":" Entry (OscalBaseModel) pydantic-model","text":"

                                    Identifies an individual risk response that occurred as part of managing an identified risk.

                                    Source code in trestle/oscal/common.py
                                    class Entry(OscalBaseModel):\n\"\"\"\n    Identifies an individual risk response that occurred as part of managing an identified risk.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk log entry elsewhere in this or other OSCAL instances. The locally defined UUID of the risk log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Risk Log Entry Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this risk log entry.', title='Title')\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of what was done regarding the risk.',\n        title='Risk Task Description'\n    )\n    start: datetime = Field(..., description='Identifies the start date and time of the event.', title='Start')\n    end: Optional[datetime] = Field(\n        None,\n        description=\n        'Identifies the end date and time of the event. If the event is a point in time, the start and end will be the same date and time.',\n        title='End'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    logged_by: Optional[List[LoggedBy]] = Field(None, alias='logged-by')\n    status_change: Optional[RiskStatus] = Field(None, alias='status-change')\n    related_responses: Optional[List[RelatedResponse]] = Field(None, alias='related-responses')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of what was done regarding the risk.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.end","title":"end: datetime pydantic-field","text":"

                                    Identifies the end date and time of the event. If the event is a point in time, the start and end will be the same date and time.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.logged_by","title":"logged_by: List[trestle.oscal.common.LoggedBy] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.related_responses","title":"related_responses: List[trestle.oscal.common.RelatedResponse] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.start","title":"start: datetime pydantic-field required","text":"

                                    Identifies the start date and time of the event.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.status_change","title":"status_change: RiskStatus pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.title","title":"title: str pydantic-field","text":"

                                    The title for this risk log entry.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk log entry elsewhere in this or other OSCAL instances. The locally defined UUID of the risk log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId","title":" ExternalId (OscalBaseModel) pydantic-model","text":"

                                    An identifier for a person or organization using a designated scheme. e.g. an Open Researcher and Contributor ID (ORCID).

                                    Source code in trestle/oscal/common.py
                                    class ExternalId(OscalBaseModel):\n\"\"\"\n    An identifier for a person or organization using a designated scheme. e.g. an Open Researcher and Contributor ID (ORCID).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    scheme: Union[URIDatatype, ExternalSchemeValidValues] = Field(\n        ..., description='Indicates the type of external identifier.', title='External Identifier Schema'\n    )\n    id: constr(regex=r'^\\S(.*\\S)?$')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.id","title":"id: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.scheme","title":"scheme: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.ExternalSchemeValidValues] pydantic-field required","text":"

                                    Indicates the type of external identifier.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalSchemeValidValues","title":" ExternalSchemeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class ExternalSchemeValidValues(Enum):\n    http___orcid_org_ = 'http://orcid.org/'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet","title":" Facet (OscalBaseModel) pydantic-model","text":"

                                    An individual characteristic that is part of a larger set produced by the same actor.

                                    Source code in trestle/oscal/common.py
                                    class Facet(OscalBaseModel):\n\"\"\"\n    An individual characteristic that is part of a larger set produced by the same actor.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    name: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., description='The name of the risk metric within the specified system.', title='Facet Name')\n    system: Union[URIDatatype, NamingSystemValidValues] = Field(\n        ...,\n        description=\n        'Specifies the naming system under which this risk metric is organized, which allows for the same names to be used in different systems controlled by different parties. This avoids the potential of a name clash.',\n        title='Naming System'\n    )\n    value: constr(regex=r'^\\S(.*\\S)?$'\n                  ) = Field(..., description='Indicates the value of the facet.', title='Facet Value')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                    The name of the risk metric within the specified system.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.system","title":"system: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.NamingSystemValidValues] pydantic-field required","text":"

                                    Specifies the naming system under which this risk metric is organized, which allows for the same names to be used in different systems controlled by different parties. This avoids the potential of a name clash.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.value","title":"value: ConstrainedStrValue pydantic-field required","text":"

                                    Indicates the value of the facet.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding","title":" Finding (OscalBaseModel) pydantic-model","text":"

                                    Describes an individual finding.

                                    Source code in trestle/oscal/common.py
                                    class Finding(OscalBaseModel):\n\"\"\"\n    Describes an individual finding.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this finding in this or other OSCAL instances. The locally defined UUID of the finding can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Finding Universally Unique Identifier',\n    )\n    title: str = Field(..., description='The title for this finding.', title='Finding Title')\n    description: str = Field(\n        ..., description='A human-readable description of this finding.', title='Finding Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    origins: Optional[List[Origin]] = Field(None)\n    target: FindingTarget\n    implementation_statement_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='implementation-statement-uuid',\n        description=\n        'A machine-oriented identifier reference to the implementation statement in the SSP to which this finding is related.',\n        title='Implementation Statement UUID'\n    )\n    related_observations: Optional[List[RelatedObservation]] = Field(None, alias='related-observations')\n    related_risks: Optional[List[RelatedRisk]] = Field(None, alias='related-risks')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this finding.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.implementation_statement_uuid","title":"implementation_statement_uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented identifier reference to the implementation statement in the SSP to which this finding is related.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.related_observations","title":"related_observations: List[trestle.oscal.common.RelatedObservation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.related_risks","title":"related_risks: List[trestle.oscal.common.RelatedRisk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.target","title":"target: FindingTarget pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.title","title":"title: str pydantic-field required","text":"

                                    The title for this finding.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this finding in this or other OSCAL instances. The locally defined UUID of the finding can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget","title":" FindingTarget (OscalBaseModel) pydantic-model","text":"

                                    Captures an assessor's conclusions regarding the degree to which an objective is satisfied.

                                    Source code in trestle/oscal/common.py
                                    class FindingTarget(OscalBaseModel):\n\"\"\"\n    Captures an assessor's conclusions regarding the degree to which an objective is satisfied.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: FindingTargetTypeValidValues = Field(\n        ..., description='Identifies the type of the target.', title='Finding Target Type'\n    )\n    target_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='target-id',\n        description='A machine-oriented identifier reference for a specific target qualified by the type.',\n        title='Finding Target Identifier Reference'\n    )\n    title: Optional[str] = Field(\n        None, description='The title for this objective status.', title='Objective Status Title'\n    )\n    description: Optional[str] = Field(\n        None,\n        description=\n        \"A human-readable description of the assessor's conclusions regarding the degree to which an objective is satisfied.\",\n        title='Objective Status Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    implementation_status: Optional[ImplementationStatus] = Field(None, alias='implementation-status')\n    remarks: Optional[str] = None\n    status: Optional[ObjectiveStatus] = Field(\n        None,\n        description='A determination of if the objective is satisfied or not within a given system.',\n        title='Objective Status'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of the assessor's conclusions regarding the degree to which an objective is satisfied.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.implementation_status","title":"implementation_status: ImplementationStatus pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.status","title":"status: ObjectiveStatus pydantic-field","text":"

                                    A determination of if the objective is satisfied or not within a given system.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.target_id","title":"target_id: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference for a specific target qualified by the type.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.title","title":"title: str pydantic-field","text":"

                                    The title for this objective status.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.type","title":"type: FindingTargetTypeValidValues pydantic-field required","text":"

                                    Identifies the type of the target.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTargetTypeValidValues","title":" FindingTargetTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class FindingTargetTypeValidValues(Enum):\n    statement_id = 'statement-id'\n    objective_id = 'objective-id'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTargetTypeValidValues.objective_id","title":"objective_id","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTargetTypeValidValues.statement_id","title":"statement_id","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed","title":" FunctionPerformed (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class FunctionPerformed(OscalBaseModel):\n    __root__: StringDatatype = Field(\n        ...,\n        description='Describes a function performed for a given authorized privilege by this user class.',\n        title='Functions Performed'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                    Describes a function performed for a given authorized privilege by this user class.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash","title":" Hash (OscalBaseModel) pydantic-model","text":"

                                    A representation of a cryptographic digest generated over a resource using a specified hash algorithm.

                                    Source code in trestle/oscal/common.py
                                    class Hash(OscalBaseModel):\n\"\"\"\n    A representation of a cryptographic digest generated over a resource using a specified hash algorithm.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    algorithm: Union[constr(regex=r'^\\S(.*\\S)?$'), Algorithm] = Field(\n        ..., description='The digest method by which a hash is derived.', title='Hash algorithm'\n    )\n    value: constr(regex=r'^\\S(.*\\S)?$')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.algorithm","title":"algorithm: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Algorithm] pydantic-field required","text":"

                                    The digest method by which a hash is derived.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.value","title":"value: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowMany","title":" HowMany (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class HowManyValidValues(Enum):\n    one = 'one'\n    one_or_more = 'one-or-more'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowMany.one","title":"one","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowMany.one_or_more","title":"one_or_more","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowManyValidValues","title":" HowManyValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class HowManyValidValues(Enum):\n    one = 'one'\n    one_or_more = 'one-or-more'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowManyValidValues.one","title":"one","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowManyValidValues.one_or_more","title":"one_or_more","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject","title":" IdentifiedSubject (OscalBaseModel) pydantic-model","text":"

                                    Used to detail assessment subjects that were identfied by this task.

                                    Source code in trestle/oscal/common.py
                                    class IdentifiedSubject(OscalBaseModel):\n\"\"\"\n    Used to detail assessment subjects that were identfied by this task.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    subject_placeholder_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='subject-placeholder-uuid',\n        description=\n        'A machine-oriented identifier reference to a unique assessment subject placeholder defined by this task.',\n        title='Assessment Subject Placeholder Universally Unique Identifier Reference'\n    )\n    subjects: List[AssessmentSubject] = Field(...)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.subject_placeholder_uuid","title":"subject_placeholder_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a unique assessment subject placeholder defined by this task.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType","title":" IdentifierType (Enum) ","text":"

                                    Identifies the identification system from which the provided identifier was assigned.

                                    Source code in trestle/oscal/common.py
                                    class IdentifierType(Enum):\n\"\"\"\n    Identifies the identification system from which the provided identifier was assigned.\n    \"\"\"\n\n    https___fedramp_gov = 'https://fedramp.gov'\n    http___fedramp_gov_ns_oscal = 'http://fedramp.gov/ns/oscal'\n    https___ietf_org_rfc_rfc4122 = 'https://ietf.org/rfc/rfc4122'\n    http___ietf_org_rfc_rfc4122 = 'http://ietf.org/rfc/rfc4122'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.http___fedramp_gov_ns_oscal","title":"http___fedramp_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.http___ietf_org_rfc_rfc4122","title":"http___ietf_org_rfc_rfc4122","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.https___fedramp_gov","title":"https___fedramp_gov","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.https___ietf_org_rfc_rfc4122","title":"https___ietf_org_rfc_rfc4122","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus","title":" ImplementationStatus (OscalBaseModel) pydantic-model","text":"

                                    Indicates the degree to which the a given control is implemented.

                                    Source code in trestle/oscal/common.py
                                    class ImplementationStatus(OscalBaseModel):\n\"\"\"\n    Indicates the degree to which the a given control is implemented.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                 State] = Field(\n                     ...,\n                     description='Identifies the implementation status of the control or control objective.',\n                     title='Implementation State'\n                 )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.state","title":"state: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.State] pydantic-field required","text":"

                                    Identifies the implementation status of the control or control objective.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent","title":" ImplementedComponent (OscalBaseModel) pydantic-model","text":"

                                    The set of components that are implemented in a given system inventory item.

                                    Source code in trestle/oscal/common.py
                                    class ImplementedComponent(OscalBaseModel):\n\"\"\"\n    The set of components that are implemented in a given system inventory item.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description=\n        'A machine-oriented identifier reference to a component that is implemented as part of an inventory item.',\n        title='Component Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a component that is implemented as part of an inventory item.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp","title":" ImportSsp (OscalBaseModel) pydantic-model","text":"

                                    Used by the assessment plan and POA&M to import information about the system.

                                    Source code in trestle/oscal/common.py
                                    class ImportSsp(OscalBaseModel):\n\"\"\"\n    Used by the assessment plan and POA&M to import information about the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description='A resolvable URL reference to the system security plan for the system being assessed.',\n        title='System Security Plan Reference'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.href","title":"href: str pydantic-field required","text":"

                                    A resolvable URL reference to the system security plan for the system being assessed.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll","title":" IncludeAll (OscalBaseModel) pydantic-model","text":"

                                    Include all controls from the imported catalog or profile resources.

                                    Source code in trestle/oscal/common.py
                                    class IncludeAll(OscalBaseModel):\n\"\"\"\n    Include all controls from the imported catalog or profile resources.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype","title":" IntegerDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class IntegerDatatype(OscalBaseModel):\n    __root__: int = Field(..., description='A whole number value.')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__root__","title":"__root__: int pydantic-field required special","text":"

                                    A whole number value.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem","title":" InventoryItem (OscalBaseModel) pydantic-model","text":"

                                    A single managed inventory item within the system.

                                    Source code in trestle/oscal/common.py
                                    class InventoryItem(OscalBaseModel):\n\"\"\"\n    A single managed inventory item within the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inventory item elsewhere in this or other OSCAL instances. The locally defined UUID of the inventory item can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Inventory Item Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description='A summary of the inventory item stating its purpose within the system.',\n        title='Inventory Item Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    implemented_components: Optional[List[ImplementedComponent]] = Field(None, alias='implemented-components')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.description","title":"description: str pydantic-field required","text":"

                                    A summary of the inventory item stating its purpose within the system.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.implemented_components","title":"implemented_components: List[trestle.oscal.common.ImplementedComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inventory item elsewhere in this or other OSCAL instances. The locally defined UUID of the inventory item can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective","title":" JsonSchemaDirective (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class JsonSchemaDirective(OscalBaseModel):\n    __root__: URIReferenceDatatype = Field(\n        ...,\n        description='A JSON Schema directive to bind a specific schema to its document instance.',\n        title='Schema Directive'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__root__","title":"__root__: URIReferenceDatatype pydantic-field required special","text":"

                                    A JSON Schema directive to bind a specific schema to its document instance.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified","title":" LastModified (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class LastModified(OscalBaseModel):\n    __root__: DateTimeWithTimezoneDatatype = Field(\n        ...,\n        description='The date and time the document was last stored for later retrieval.',\n        title='Last Modified Timestamp'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__root__","title":"__root__: DateTimeWithTimezoneDatatype pydantic-field required special","text":"

                                    The date and time the document was last stored for later retrieval.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle","title":" Lifecycle (Enum) ","text":"

                                    Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.

                                    Source code in trestle/oscal/common.py
                                    class Lifecycle(Enum):\n\"\"\"\n    Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.\n    \"\"\"\n\n    recommendation = 'recommendation'\n    planned = 'planned'\n    completed = 'completed'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle.completed","title":"completed","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle.planned","title":"planned","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle.recommendation","title":"recommendation","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link","title":" Link (OscalBaseModel) pydantic-model","text":"

                                    A reference to a local or remote resource, that has a specific relation to the containing object.

                                    Source code in trestle/oscal/common.py
                                    class Link(OscalBaseModel):\n\"\"\"\n    A reference to a local or remote resource, that has a specific relation to the containing object.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(..., description='A resolvable URL reference to a resource.', title='Hypertext Reference')\n    rel: Optional[\n        Union[constr(\n            regex=\n            r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n        ),\n              Rel]\n    ] = Field(\n        None,\n        description=\n        \"Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.\",\n        title='Link Relation Type'\n    )\n    media_type: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='media-type',\n        description='A label that indicates the nature of a resource, as a data serialization or format.',\n        title='Media Type'\n    )\n    resource_fragment: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='resource-fragment',\n        description=\n        'In case where the href points to a back-matter/resource, this value will indicate the URI fragment to append to any rlink associated with the resource. This value MUST be URI encoded.',\n        title='Resource Fragment'\n    )\n    text: Optional[str] = Field(\n        None,\n        description='A textual label to associate with the link, which may be used for presentation in a tool.',\n        title='Link Text'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.href","title":"href: str pydantic-field required","text":"

                                    A resolvable URL reference to a resource.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.media_type","title":"media_type: ConstrainedStrValue pydantic-field","text":"

                                    A label that indicates the nature of a resource, as a data serialization or format.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.rel","title":"rel: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Rel] pydantic-field","text":"

                                    Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.resource_fragment","title":"resource_fragment: ConstrainedStrValue pydantic-field","text":"

                                    In case where the href points to a back-matter/resource, this value will indicate the URI fragment to append to any rlink associated with the resource. This value MUST be URI encoded.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.text","title":"text: str pydantic-field","text":"

                                    A textual label to associate with the link, which may be used for presentation in a tool.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective","title":" LocalObjective (OscalBaseModel) pydantic-model","text":"

                                    A local definition of a control objective for this assessment. Uses catalog syntax for control objective and assessment actions.

                                    Source code in trestle/oscal/common.py
                                    class LocalObjective(OscalBaseModel):\n\"\"\"\n    A local definition of a control objective for this assessment. Uses catalog syntax for control objective and assessment actions.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    description: Optional[str] = Field(\n        None, description='A human-readable description of this control objective.', title='Objective Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    parts: List[Part] = Field(...)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                    A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of this control objective.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location","title":" Location (OscalBaseModel) pydantic-model","text":"

                                    A physical point of presence, which may be associated with people, organizations, or other concepts within the current or linked OSCAL document.

                                    Source code in trestle/oscal/common.py
                                    class Location(OscalBaseModel):\n\"\"\"\n    A physical point of presence, which may be associated with people, organizations, or other concepts within the current or linked OSCAL document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='A unique ID for the location, for reference.',\n                     title='Location Universally Unique Identifier'\n                 )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the location, which may be used by a tool for display and navigation.',\n        title='Location Title'\n    )\n    address: Optional[Address] = None\n    email_addresses: Optional[List[EmailAddress]] = Field(None, alias='email-addresses')\n    telephone_numbers: Optional[List[TelephoneNumber]] = Field(None, alias='telephone-numbers')\n    urls: Optional[List[AnyUrl]] = Field(None)\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.address","title":"address: Address pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.email_addresses","title":"email_addresses: List[trestle.oscal.common.EmailAddress] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.telephone_numbers","title":"telephone_numbers: List[trestle.oscal.common.TelephoneNumber] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.title","title":"title: str pydantic-field","text":"

                                    A name given to the location, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.urls","title":"urls: List[pydantic.v1.networks.AnyUrl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A unique ID for the location, for reference.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid","title":" LocationUuid (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class LocationUuid(OscalBaseModel):\n    __root__: UUIDDatatype = Field(\n        ..., description='Reference to a location by UUID.', title='Location Universally Unique Identifier Reference'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__root__","title":"__root__: UUIDDatatype pydantic-field required special","text":"

                                    Reference to a location by UUID.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy","title":" LoggedBy (OscalBaseModel) pydantic-model","text":"

                                    Used to indicate who created a log entry in what role.

                                    Source code in trestle/oscal/common.py
                                    class LoggedBy(OscalBaseModel):\n\"\"\"\n    Used to indicate who created a log entry in what role.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    party_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='party-uuid',\n        description='A machine-oriented identifier reference to the party who is making the log entry.',\n        title='Party UUID Reference'\n    )\n    role_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='role-id',\n        description='A point to the role-id of the role in which the party is making the log entry.',\n        title='Actor Role'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.party_uuid","title":"party_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to the party who is making the log entry.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.role_id","title":"role_id: ConstrainedStrValue pydantic-field","text":"

                                    A point to the role-id of the role in which the party is making the log entry.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata","title":" Metadata (OscalBaseModel) pydantic-model","text":"

                                    Provides information about the containing document, and defines concepts that are shared across the document.

                                    Source code in trestle/oscal/common.py
                                    class Metadata(OscalBaseModel):\n\"\"\"\n    Provides information about the containing document, and defines concepts that are shared across the document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    title: str = Field(\n        ...,\n        description='A name given to the document, which may be used by a tool for display and navigation.',\n        title='Document Title'\n    )\n    published: Optional[datetime] = None\n    last_modified: datetime = Field(..., alias='last-modified')\n    version: constr(regex=r'^\\S(.*\\S)?$')\n    oscal_version: OscalVersion = Field(..., alias='oscal-version')\n    revisions: Optional[List[Revision]] = Field(None)\n    document_ids: Optional[List[DocumentId]] = Field(None, alias='document-ids')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    roles: Optional[List[Role]] = Field(None)\n    locations: Optional[List[Location]] = Field(None)\n    parties: Optional[List[Party]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    actions: Optional[List[Action]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.actions","title":"actions: List[trestle.oscal.common.Action] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.document_ids","title":"document_ids: List[trestle.oscal.common.DocumentId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.last_modified","title":"last_modified: datetime pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.locations","title":"locations: List[trestle.oscal.common.Location] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.oscal_version","title":"oscal_version: OscalVersion pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.parties","title":"parties: List[trestle.oscal.common.Party] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.published","title":"published: datetime pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.revisions","title":"revisions: List[trestle.oscal.common.Revision] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.roles","title":"roles: List[trestle.oscal.common.Role] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.title","title":"title: str pydantic-field required","text":"

                                    A name given to the document, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.version","title":"version: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods","title":" Methods (Enum) ","text":"

                                    Identifies how the observation was made.

                                    Source code in trestle/oscal/common.py
                                    class Methods(Enum):\n\"\"\"\n    Identifies how the observation was made.\n    \"\"\"\n\n    EXAMINE = 'EXAMINE'\n    INTERVIEW = 'INTERVIEW'\n    TEST = 'TEST'\n    UNKNOWN = 'UNKNOWN'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.EXAMINE","title":"EXAMINE","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.INTERVIEW","title":"INTERVIEW","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.TEST","title":"TEST","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.UNKNOWN","title":"UNKNOWN","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor","title":" MitigatingFactor (OscalBaseModel) pydantic-model","text":"

                                    Describes an existing mitigating factor that may affect the overall determination of the risk, with an optional link to an implementation statement in the SSP.

                                    Source code in trestle/oscal/common.py
                                    class MitigatingFactor(OscalBaseModel):\n\"\"\"\n    Describes an existing mitigating factor that may affect the overall determination of the risk, with an optional link to an implementation statement in the SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this mitigating factor elsewhere in this or other OSCAL instances. The locally defined UUID of the mitigating factor can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Mitigating Factor Universally Unique Identifier',\n    )\n    implementation_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='implementation-uuid',\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this implementation statement elsewhere in this or other OSCAL instancess. The locally defined UUID of the implementation statement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Implementation UUID',\n    )\n    description: str = Field(\n        ...,\n        description='A human-readable description of this mitigating factor.',\n        title='Mitigating Factor Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    subjects: Optional[List[SubjectReference]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this mitigating factor.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.implementation_uuid","title":"implementation_uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this implementation statement elsewhere in this or other OSCAL instancess. The locally defined UUID of the implementation statement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.subjects","title":"subjects: List[trestle.oscal.common.SubjectReference] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this mitigating factor elsewhere in this or other OSCAL instances. The locally defined UUID of the mitigating factor can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name","title":" Name (Enum) ","text":"

                                    A textual label that uniquely identifies the part's semantic type.

                                    Source code in trestle/oscal/common.py
                                    class Name(Enum):\n\"\"\"\n    A textual label that uniquely identifies the part's semantic type.\n    \"\"\"\n\n    asset = 'asset'\n    method = 'method'\n    objective = 'objective'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name.asset","title":"asset","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name.method","title":"method","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name.objective","title":"objective","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues","title":" NamingSystemValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class NamingSystemValidValues(Enum):\n    http___fedramp_gov = 'http://fedramp.gov'\n    http___fedramp_gov_ns_oscal = 'http://fedramp.gov/ns/oscal'\n    http___csrc_nist_gov_ns_oscal = 'http://csrc.nist.gov/ns/oscal'\n    http___csrc_nist_gov_ns_oscal_unknown = 'http://csrc.nist.gov/ns/oscal/unknown'\n    http___cve_mitre_org = 'http://cve.mitre.org'\n    http___www_first_org_cvss_v2_0 = 'http://www.first.org/cvss/v2.0'\n    http___www_first_org_cvss_v3_0 = 'http://www.first.org/cvss/v3.0'\n    http___www_first_org_cvss_v3_1 = 'http://www.first.org/cvss/v3.1'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___csrc_nist_gov_ns_oscal","title":"http___csrc_nist_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___csrc_nist_gov_ns_oscal_unknown","title":"http___csrc_nist_gov_ns_oscal_unknown","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___cve_mitre_org","title":"http___cve_mitre_org","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___fedramp_gov","title":"http___fedramp_gov","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___fedramp_gov_ns_oscal","title":"http___fedramp_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___www_first_org_cvss_v2_0","title":"http___www_first_org_cvss_v2_0","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___www_first_org_cvss_v3_0","title":"http___www_first_org_cvss_v3_0","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___www_first_org_cvss_v3_1","title":"http___www_first_org_cvss_v3_1","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype","title":" NonNegativeIntegerDatatype (OscalBaseModel) pydantic-model","text":"

                                    An integer value that is equal to or greater than 0.

                                    Source code in trestle/oscal/common.py
                                    class NonNegativeIntegerDatatype(OscalBaseModel):\n\"\"\"\n    An integer value that is equal to or greater than 0.\n    \"\"\"\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus","title":" ObjectiveStatus (OscalBaseModel) pydantic-model","text":"

                                    A determination of if the objective is satisfied or not within a given system.

                                    Source code in trestle/oscal/common.py
                                    class ObjectiveStatus(OscalBaseModel):\n\"\"\"\n    A determination of if the objective is satisfied or not within a given system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: ObjectiveStatusStateValidValues = Field(\n        ...,\n        description='An indication as to whether the objective is satisfied or not.',\n        title='Objective Status State'\n    )\n    reason: Optional[Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                           Reason]] = Field(\n                               None,\n                               description=\"The reason the objective was given it's status.\",\n                               title='Objective Status Reason'\n                           )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.reason","title":"reason: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Reason] pydantic-field","text":"

                                    The reason the objective was given it's status.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.state","title":"state: ObjectiveStatusStateValidValues pydantic-field required","text":"

                                    An indication as to whether the objective is satisfied or not.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatusStateValidValues","title":" ObjectiveStatusStateValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class ObjectiveStatusStateValidValues(Enum):\n    satisfied = 'satisfied'\n    not_satisfied = 'not-satisfied'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatusStateValidValues.not_satisfied","title":"not_satisfied","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatusStateValidValues.satisfied","title":"satisfied","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation","title":" Observation (OscalBaseModel) pydantic-model","text":"

                                    Describes an individual observation.

                                    Source code in trestle/oscal/common.py
                                    class Observation(OscalBaseModel):\n\"\"\"\n    Describes an individual observation.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this observation elsewhere in this or other OSCAL instances. The locally defined UUID of the observation can be used to reference the data item locally or globally (e.g., in an imorted OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Observation Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this observation.', title='Observation Title')\n    description: str = Field(\n        ...,\n        description='A human-readable description of this assessment observation.',\n        title='Observation Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    methods: List[Union[constr(regex=r'^\\S(.*\\S)?$'), Methods]] = Field(...)\n    types: Optional[List[Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                               ObservationTypeValidValues]]] = Field(None)\n    origins: Optional[List[Origin]] = Field(None)\n    subjects: Optional[List[SubjectReference]] = Field(None)\n    relevant_evidence: Optional[List[RelevantEvidence]] = Field(None, alias='relevant-evidence')\n    collected: datetime = Field(\n        ...,\n        description='Date/time stamp identifying when the finding information was collected.',\n        title='Collected Field'\n    )\n    expires: Optional[datetime] = Field(\n        None,\n        description=\n        'Date/time identifying when the finding information is out-of-date and no longer valid. Typically used with continuous assessment scenarios.',\n        title='Expires Field'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.collected","title":"collected: datetime pydantic-field required","text":"

                                    Date/time stamp identifying when the finding information was collected.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this assessment observation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.expires","title":"expires: datetime pydantic-field","text":"

                                    Date/time identifying when the finding information is out-of-date and no longer valid. Typically used with continuous assessment scenarios.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.methods","title":"methods: List[Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Methods]] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.relevant_evidence","title":"relevant_evidence: List[trestle.oscal.common.RelevantEvidence] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.subjects","title":"subjects: List[trestle.oscal.common.SubjectReference] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.title","title":"title: str pydantic-field","text":"

                                    The title for this observation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.types","title":"types: List[Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.ObservationTypeValidValues]] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this observation elsewhere in this or other OSCAL instances. The locally defined UUID of the observation can be used to reference the data item locally or globally (e.g., in an imorted OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues","title":" ObservationTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class ObservationTypeValidValues(Enum):\n    ssp_statement_issue = 'ssp-statement-issue'\n    control_objective = 'control-objective'\n    mitigation = 'mitigation'\n    finding = 'finding'\n    historic = 'historic'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.control_objective","title":"control_objective","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.finding","title":"finding","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.historic","title":"historic","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.mitigation","title":"mitigation","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.ssp_statement_issue","title":"ssp_statement_issue","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate","title":" OnDate (OscalBaseModel) pydantic-model","text":"

                                    The task is intended to occur on the specified date.

                                    Source code in trestle/oscal/common.py
                                    class OnDate(OscalBaseModel):\n\"\"\"\n    The task is intended to occur on the specified date.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    date: datetime = Field(..., description='The task must occur on the specified date.', title='On Date Condition')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.date","title":"date: datetime pydantic-field required","text":"

                                    The task must occur on the specified date.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin","title":" Origin (OscalBaseModel) pydantic-model","text":"

                                    Identifies the source of the finding, such as a tool, interviewed person, or activity.

                                    Source code in trestle/oscal/common.py
                                    class Origin(OscalBaseModel):\n\"\"\"\n    Identifies the source of the finding, such as a tool, interviewed person, or activity.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    actors: List[OriginActor] = Field(...)\n    related_tasks: Optional[List[RelatedTask]] = Field(None, alias='related-tasks')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.actors","title":"actors: List[trestle.oscal.common.OriginActor] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.related_tasks","title":"related_tasks: List[trestle.oscal.common.RelatedTask] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor","title":" OriginActor (OscalBaseModel) pydantic-model","text":"

                                    The actor that produces an observation, a finding, or a risk. One or more actor type can be used to specify a person that is using a tool.

                                    Source code in trestle/oscal/common.py
                                    class OriginActor(OscalBaseModel):\n\"\"\"\n    The actor that produces an observation, a finding, or a risk. One or more actor type can be used to specify a person that is using a tool.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: OriginActorValidValues = Field(..., description='The kind of actor.', title='Actor Type')\n    actor_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='actor-uuid',\n        description='A machine-oriented identifier reference to the tool or person based on the associated type.',\n        title='Actor Universally Unique Identifier Reference'\n    )\n    role_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='role-id',\n        description='For a party, this can optionally be used to specify the role the actor was performing.',\n        title='Actor Role'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.actor_uuid","title":"actor_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to the tool or person based on the associated type.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.role_id","title":"role_id: ConstrainedStrValue pydantic-field","text":"

                                    For a party, this can optionally be used to specify the role the actor was performing.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.type","title":"type: OriginActorValidValues pydantic-field required","text":"

                                    The kind of actor.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues","title":" OriginActorValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class OriginActorValidValues(Enum):\n    tool = 'tool'\n    assessment_platform = 'assessment-platform'\n    party = 'party'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues.assessment_platform","title":"assessment_platform","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues.tool","title":"tool","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion","title":" OscalVersion (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class OscalVersion(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description='The OSCAL model version the document was authored against and will conform to as valid.',\n        title='OSCAL Version'\n    )\n\n    @validator('__root__')\n    def oscal_version_is_valid(cls, v):\n        strict_version = False\n        if not strict_version:\n            return v\n        p = re.compile(OSCAL_VERSION_REGEX)\n        matched = p.match(v)\n        if matched is None:\n            raise ValueError(f'OSCAL version: {v} is not supported, use {OSCAL_VERSION} instead.')\n        return v\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    The OSCAL model version the document was authored against and will conform to as valid.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.oscal_version_is_valid","title":"oscal_version_is_valid(v) classmethod","text":"Source code in trestle/oscal/common.py
                                    @validator('__root__')\ndef oscal_version_is_valid(cls, v):\n    strict_version = False\n    if not strict_version:\n        return v\n    p = re.compile(OSCAL_VERSION_REGEX)\n    matched = p.match(v)\n    if matched is None:\n        raise ValueError(f'OSCAL version: {v} is not supported, use {OSCAL_VERSION} instead.')\n    return v\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter","title":" Parameter (OscalBaseModel) pydantic-model","text":"

                                    Parameters provide a mechanism for the dynamic assignment of value(s) in a control.

                                    Source code in trestle/oscal/common.py
                                    class Parameter(OscalBaseModel):\n\"\"\"\n    Parameters provide a mechanism for the dynamic assignment of value(s) in a control.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., description='A unique identifier for the parameter.', title='Parameter Identifier')\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\n        'A textual label that provides a characterization of the type, purpose, use or scope of the parameter.',\n        title='Parameter Class'\n    )\n    depends_on: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='depends-on',\n        description=\n        '(deprecated) Another parameter invoking this one. This construct has been deprecated and should not be used.',\n        title='Depends on'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    label: Optional[str] = Field(\n        None,\n        description=\n        'A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.',\n        title='Parameter Label'\n    )\n    usage: Optional[str] = Field(\n        None, description='Describes the purpose and use of a parameter.', title='Parameter Usage Description'\n    )\n    constraints: Optional[List[ParameterConstraint]] = Field(None)\n    guidelines: Optional[List[ParameterGuideline]] = Field(None)\n    values: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None)\n    select: Optional[ParameterSelection] = None\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    A textual label that provides a characterization of the type, purpose, use or scope of the parameter.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.constraints","title":"constraints: List[trestle.oscal.common.ParameterConstraint] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.depends_on","title":"depends_on: ConstrainedStrValue pydantic-field","text":"

                                    (deprecated) Another parameter invoking this one. This construct has been deprecated and should not be used.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.guidelines","title":"guidelines: List[trestle.oscal.common.ParameterGuideline] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.id","title":"id: ConstrainedStrValue pydantic-field required","text":"

                                    A unique identifier for the parameter.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.label","title":"label: str pydantic-field","text":"

                                    A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.select","title":"select: ParameterSelection pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.usage","title":"usage: str pydantic-field","text":"

                                    Describes the purpose and use of a parameter.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint","title":" ParameterConstraint (OscalBaseModel) pydantic-model","text":"

                                    A formal or informal expression of a constraint or test.

                                    Source code in trestle/oscal/common.py
                                    class ParameterConstraint(OscalBaseModel):\n\"\"\"\n    A formal or informal expression of a constraint or test.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None, description='A textual summary of the constraint to be applied.', title='Constraint Description'\n    )\n    tests: Optional[List[Test]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.description","title":"description: str pydantic-field","text":"

                                    A textual summary of the constraint to be applied.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.tests","title":"tests: List[trestle.oscal.common.Test] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline","title":" ParameterGuideline (OscalBaseModel) pydantic-model","text":"

                                    A prose statement that provides a recommendation for the use of a parameter.

                                    Source code in trestle/oscal/common.py
                                    class ParameterGuideline(OscalBaseModel):\n\"\"\"\n    A prose statement that provides a recommendation for the use of a parameter.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    prose: str = Field(..., description='Prose permits multiple paragraphs, lists, tables etc.', title='Guideline Text')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.prose","title":"prose: str pydantic-field required","text":"

                                    Prose permits multiple paragraphs, lists, tables etc.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection","title":" ParameterSelection (OscalBaseModel) pydantic-model","text":"

                                    Presenting a choice among alternatives.

                                    Source code in trestle/oscal/common.py
                                    class ParameterSelection(OscalBaseModel):\n\"\"\"\n    Presenting a choice among alternatives.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    how_many: Optional[HowManyValidValues] = Field(\n        None,\n        alias='how-many',\n        description=\n        'Describes the number of selections that must occur. Without this setting, only one value should be assumed to be permitted.',\n        title='Parameter Cardinality'\n    )\n    choice: Optional[List[str]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.choice","title":"choice: List[str] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.how_many","title":"how_many: HowManyValidValues pydantic-field","text":"

                                    Describes the number of selections that must occur. Without this setting, only one value should be assumed to be permitted.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue","title":" ParameterValue (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class ParameterValue(OscalBaseModel):\n    __root__: StringDatatype = Field(..., description='A parameter value or set of values.', title='Parameter Value')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                    A parameter value or set of values.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part","title":" Part (OscalBaseModel) pydantic-model","text":"

                                    An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.

                                    Source code in trestle/oscal/common.py
                                    class Part(OscalBaseModel):\n\"\"\"\n    An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, description='A unique identifier for the part.', title='Part Identifier'\n    )\n    name: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        \"A textual label that uniquely identifies the part's semantic type, which exists in a value space qualified by the ns.\",\n        title='Part Name'\n    )\n    ns: Optional[AnyUrl] = Field(\n        None,\n        description=\n        \"An optional namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.\",\n        title='Part Namespace'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\n        \"An optional textual providing a sub-type or characterization of the part's name, or a category to which the part belongs.\",\n        title='Part Class'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='An optional name given to the part, which may be used by a tool for display and navigation.',\n        title='Part Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    prose: Optional[str] = Field(None, description='Permits multiple paragraphs, lists, tables etc.', title='Part Text')\n    parts: Optional[List[Part]] = None\n    links: Optional[List[Link]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    An optional textual providing a sub-type or characterization of the part's name, or a category to which the part belongs.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.id","title":"id: ConstrainedStrValue pydantic-field","text":"

                                    A unique identifier for the part.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                    A textual label that uniquely identifies the part's semantic type, which exists in a value space qualified by the ns.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.ns","title":"ns: AnyUrl pydantic-field","text":"

                                    An optional namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.prose","title":"prose: str pydantic-field","text":"

                                    Permits multiple paragraphs, lists, tables etc.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.title","title":"title: str pydantic-field","text":"

                                    An optional name given to the part, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party","title":" Party (OscalBaseModel) pydantic-model","text":"

                                    An organization or person, which may be associated with roles or other concepts within the current or linked OSCAL document.

                                    Source code in trestle/oscal/common.py
                                    class Party(OscalBaseModel):\n\"\"\"\n    An organization or person, which may be associated with roles or other concepts within the current or linked OSCAL document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(..., description='A unique identifier for the party.', title='Party Universally Unique Identifier')\n    type: PartyTypeValidValues = Field(\n        ..., description='A category describing the kind of party the object describes.', title='Party Type'\n    )\n    name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        description='The full name of the party. This is typically the legal name associated with the party.',\n        title='Party Name'\n    )\n    short_name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='short-name',\n        description='A short common name, abbreviation, or acronym for the party.',\n        title='Party Short Name'\n    )\n    external_ids: Optional[List[ExternalId]] = Field(None, alias='external-ids')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    email_addresses: Optional[List[EmailAddress]] = Field(None, alias='email-addresses')\n    telephone_numbers: Optional[List[TelephoneNumber]] = Field(None, alias='telephone-numbers')\n    addresses: Optional[List[Address]] = Field(None)\n    location_uuids: Optional[List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )]] = Field(\n        None, alias='location-uuids'\n    )\n    member_of_organizations: Optional[List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )]] = Field(\n        None, alias='member-of-organizations'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.addresses","title":"addresses: List[trestle.oscal.common.Address] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.email_addresses","title":"email_addresses: List[trestle.oscal.common.EmailAddress] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.external_ids","title":"external_ids: List[trestle.oscal.common.ExternalId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.location_uuids","title":"location_uuids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.member_of_organizations","title":"member_of_organizations: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.name","title":"name: ConstrainedStrValue pydantic-field","text":"

                                    The full name of the party. This is typically the legal name associated with the party.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.short_name","title":"short_name: ConstrainedStrValue pydantic-field","text":"

                                    A short common name, abbreviation, or acronym for the party.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.telephone_numbers","title":"telephone_numbers: List[trestle.oscal.common.TelephoneNumber] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.type","title":"type: PartyTypeValidValues pydantic-field required","text":"

                                    A category describing the kind of party the object describes.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A unique identifier for the party.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyTypeValidValues","title":" PartyTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class PartyTypeValidValues(Enum):\n    person = 'person'\n    organization = 'organization'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyTypeValidValues.organization","title":"organization","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyTypeValidValues.person","title":"person","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid","title":" PartyUuid (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class PartyUuid(OscalBaseModel):\n    __root__: UUIDDatatype = Field(\n        ..., description='Reference to a party by UUID.', title='Party Universally Unique Identifier Reference'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__root__","title":"__root__: UUIDDatatype pydantic-field required special","text":"

                                    Reference to a party by UUID.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange","title":" PortRange (OscalBaseModel) pydantic-model","text":"

                                    Where applicable this is the IPv4 port range on which the service operates.

                                    Source code in trestle/oscal/common.py
                                    class PortRange(OscalBaseModel):\n\"\"\"\n    Where applicable this is the IPv4 port range on which the service operates.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    start: Optional[conint(ge=0, multiple_of=1)] = Field(\n        None, description='Indicates the starting port number in a port range', title='Start'\n    )\n    end: Optional[conint(ge=0, multiple_of=1)] = Field(\n        None, description='Indicates the ending port number in a port range', title='End'\n    )\n    transport: Optional[PortRangeValidValues] = Field(\n        None, description='Indicates the transport type.', title='Transport'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.end","title":"end: ConstrainedIntValue pydantic-field","text":"

                                    Indicates the ending port number in a port range

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.start","title":"start: ConstrainedIntValue pydantic-field","text":"

                                    Indicates the starting port number in a port range

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.transport","title":"transport: PortRangeValidValues pydantic-field","text":"

                                    Indicates the transport type.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRangeValidValues","title":" PortRangeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class PortRangeValidValues(Enum):\n    TCP = 'TCP'\n    UDP = 'UDP'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRangeValidValues.TCP","title":"TCP","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRangeValidValues.UDP","title":"UDP","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype","title":" PositiveIntegerDatatype (OscalBaseModel) pydantic-model","text":"

                                    An integer value that is greater than 0.

                                    Source code in trestle/oscal/common.py
                                    class PositiveIntegerDatatype(OscalBaseModel):\n\"\"\"\n    An integer value that is greater than 0.\n    \"\"\"\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property","title":" Property (OscalBaseModel) pydantic-model","text":"

                                    An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.

                                    Source code in trestle/oscal/common.py
                                    class Property(OscalBaseModel):\n\"\"\"\n    An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    name: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        \"A textual label, within a namespace, that uniquely identifies a specific attribute, characteristic, or quality of the property's containing object.\",\n        title='Property Name'\n    )\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None, description='A unique identifier for a property.', title='Property Universally Unique Identifier'\n    )\n    ns: Optional[AnyUrl] = Field(\n        None,\n        description=\n        \"A namespace qualifying the property's name. This allows different organizations to associate distinct semantics with the same name.\",\n        title='Property Namespace'\n    )\n    value: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ..., description='Indicates the value of the attribute, characteristic, or quality.', title='Property Value'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\"A textual label that provides a sub-type or characterization of the property's name.\",\n        title='Property Class'\n    )\n    group: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, description='An identifier for relating distinct sets of properties.', title='Property Group'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    A textual label that provides a sub-type or characterization of the property's name.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.group","title":"group: ConstrainedStrValue pydantic-field","text":"

                                    An identifier for relating distinct sets of properties.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                    A textual label, within a namespace, that uniquely identifies a specific attribute, characteristic, or quality of the property's containing object.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.ns","title":"ns: AnyUrl pydantic-field","text":"

                                    A namespace qualifying the property's name. This allows different organizations to associate distinct semantics with the same name.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                    A unique identifier for a property.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.value","title":"value: ConstrainedStrValue pydantic-field required","text":"

                                    Indicates the value of the attribute, characteristic, or quality.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol","title":" Protocol (OscalBaseModel) pydantic-model","text":"

                                    Information about the protocol used to provide a service.

                                    Source code in trestle/oscal/common.py
                                    class Protocol(OscalBaseModel):\n\"\"\"\n    Information about the protocol used to provide a service.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this service protocol information elsewhere in this or other OSCAL instances. The locally defined UUID of the service protocol can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Service Protocol Information Universally Unique Identifier',\n    )\n    name: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description=\n        'The common name of the protocol, which should be the appropriate \"service name\" from the IANA Service Name and Transport Protocol Port Number Registry.',\n        title='Protocol Name'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A human readable name for the protocol (e.g., Transport Layer Security).',\n        title='Protocol Title'\n    )\n    port_ranges: Optional[List[PortRange]] = Field(None, alias='port-ranges')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                    The common name of the protocol, which should be the appropriate \"service name\" from the IANA Service Name and Transport Protocol Port Number Registry.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.port_ranges","title":"port_ranges: List[trestle.oscal.common.PortRange] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.title","title":"title: str pydantic-field","text":"

                                    A human readable name for the protocol (e.g., Transport Layer Security).

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this service protocol information elsewhere in this or other OSCAL instances. The locally defined UUID of the service protocol can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published","title":" Published (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class Published(OscalBaseModel):\n    __root__: DateTimeWithTimezoneDatatype = Field(\n        ..., description='The date and time the document was last made available.', title='Publication Timestamp'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__root__","title":"__root__: DateTimeWithTimezoneDatatype pydantic-field required special","text":"

                                    The date and time the document was last made available.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason","title":" Reason (Enum) ","text":"

                                    The reason the objective was given it's status.

                                    Source code in trestle/oscal/common.py
                                    class Reason(Enum):\n\"\"\"\n    The reason the objective was given it's status.\n    \"\"\"\n\n    pass_ = 'pass'\n    fail = 'fail'\n    other = 'other'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason.fail","title":"fail","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason.other","title":"other","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason.pass_","title":"pass_","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rel","title":" Rel (Enum) ","text":"

                                    Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.

                                    Source code in trestle/oscal/common.py
                                    class Rel(Enum):\n\"\"\"\n    Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.\n    \"\"\"\n\n    reference = 'reference'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rel.reference","title":"reference","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation","title":" RelatedObservation (OscalBaseModel) pydantic-model","text":"

                                    Relates the finding to a set of referenced observations that were used to determine the finding.

                                    Source code in trestle/oscal/common.py
                                    class RelatedObservation(OscalBaseModel):\n\"\"\"\n    Relates the finding to a set of referenced observations that were used to determine the finding.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    observation_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='observation-uuid',\n        description='A machine-oriented identifier reference to an observation defined in the list of observations.',\n        title='Observation Universally Unique Identifier Reference'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.observation_uuid","title":"observation_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to an observation defined in the list of observations.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse","title":" RelatedResponse (OscalBaseModel) pydantic-model","text":"

                                    Identifies an individual risk response that this log entry is for.

                                    Source code in trestle/oscal/common.py
                                    class RelatedResponse(OscalBaseModel):\n\"\"\"\n    Identifies an individual risk response that this log entry is for.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    response_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='response-uuid',\n        description='A machine-oriented identifier reference to a unique risk response.',\n        title='Response Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    related_tasks: Optional[List[RelatedTask]] = Field(None, alias='related-tasks')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.related_tasks","title":"related_tasks: List[trestle.oscal.common.RelatedTask] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.response_uuid","title":"response_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a unique risk response.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk","title":" RelatedRisk (OscalBaseModel) pydantic-model","text":"

                                    Relates the finding to a set of referenced risks that were used to determine the finding.

                                    Source code in trestle/oscal/common.py
                                    class RelatedRisk(OscalBaseModel):\n\"\"\"\n    Relates the finding to a set of referenced risks that were used to determine the finding.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    risk_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='risk-uuid',\n        description='A machine-oriented identifier reference to a risk defined in the list of risks.',\n        title='Risk Universally Unique Identifier Reference'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.risk_uuid","title":"risk_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a risk defined in the list of risks.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask","title":" RelatedTask (OscalBaseModel) pydantic-model","text":"

                                    Identifies an individual task for which the containing object is a consequence of.

                                    Source code in trestle/oscal/common.py
                                    class RelatedTask(OscalBaseModel):\n\"\"\"\n    Identifies an individual task for which the containing object is a consequence of.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    task_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='task-uuid',\n        description='A machine-oriented identifier reference to a unique task.',\n        title='Task Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    subjects: Optional[List[AssessmentSubject]] = Field(None)\n    identified_subject: Optional[IdentifiedSubject] = Field(\n        None,\n        alias='identified-subject',\n        description='Used to detail assessment subjects that were identfied by this task.',\n        title='Identified Subject'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.identified_subject","title":"identified_subject: IdentifiedSubject pydantic-field","text":"

                                    Used to detail assessment subjects that were identfied by this task.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.task_uuid","title":"task_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a unique task.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence","title":" RelevantEvidence (OscalBaseModel) pydantic-model","text":"

                                    Links this observation to relevant evidence.

                                    Source code in trestle/oscal/common.py
                                    class RelevantEvidence(OscalBaseModel):\n\"\"\"\n    Links this observation to relevant evidence.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: Optional[str] = Field(\n        None, description='A resolvable URL reference to relevant evidence.', title='Relevant Evidence Reference'\n    )\n    description: str = Field(\n        ..., description='A human-readable description of this evidence.', title='Relevant Evidence Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this evidence.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.href","title":"href: str pydantic-field","text":"

                                    A resolvable URL reference to relevant evidence.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks","title":" Remarks (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class Remarks(OscalBaseModel):\n    __root__: str = Field(..., description='Additional commentary about the containing object.', title='Remarks')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__root__","title":"__root__: str pydantic-field required special","text":"

                                    Additional commentary about the containing object.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset","title":" RequiredAsset (OscalBaseModel) pydantic-model","text":"

                                    Identifies an asset required to achieve remediation.

                                    Source code in trestle/oscal/common.py
                                    class RequiredAsset(OscalBaseModel):\n\"\"\"\n    Identifies an asset required to achieve remediation.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this required asset elsewhere in this or other OSCAL instances. The locally defined UUID of the asset can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Required Universally Unique Identifier',\n    )\n    subjects: Optional[List[SubjectReference]] = Field(None)\n    title: Optional[str] = Field(\n        None, description='The title for this required asset.', title='Title for Required Asset'\n    )\n    description: str = Field(\n        ..., description='A human-readable description of this required asset.', title='Description of Required Asset'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this required asset.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.subjects","title":"subjects: List[trestle.oscal.common.SubjectReference] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.title","title":"title: str pydantic-field","text":"

                                    The title for this required asset.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this required asset elsewhere in this or other OSCAL instances. The locally defined UUID of the asset can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource","title":" Resource (OscalBaseModel) pydantic-model","text":"

                                    A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources.

                                    Source code in trestle/oscal/common.py
                                    class Resource(OscalBaseModel):\n\"\"\"\n    A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(..., description='A unique identifier for a resource.', title='Resource Universally Unique Identifier')\n    title: Optional[str] = Field(\n        None,\n        description='An optional name given to the resource, which may be used by a tool for display and navigation.',\n        title='Resource Title'\n    )\n    description: Optional[str] = Field(\n        None,\n        description='An optional short summary of the resource used to indicate the purpose of the resource.',\n        title='Resource Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    document_ids: Optional[List[DocumentId]] = Field(None, alias='document-ids')\n    citation: Optional[Citation] = Field(\n        None, description='An optional citation consisting of end note text using structured markup.', title='Citation'\n    )\n    rlinks: Optional[List[Rlink]] = Field(None)\n    base64: Optional[Base64] = Field(\n        None, description='A resource encoded using the Base64 alphabet defined by RFC 2045.', title='Base64'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.base64","title":"base64: Base64 pydantic-field","text":"

                                    A resource encoded using the Base64 alphabet defined by RFC 2045.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.citation","title":"citation: Citation pydantic-field","text":"

                                    An optional citation consisting of end note text using structured markup.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.description","title":"description: str pydantic-field","text":"

                                    An optional short summary of the resource used to indicate the purpose of the resource.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.document_ids","title":"document_ids: List[trestle.oscal.common.DocumentId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.rlinks","title":"rlinks: List[trestle.oscal.common.Rlink] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.title","title":"title: str pydantic-field","text":"

                                    An optional name given to the resource, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A unique identifier for a resource.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response","title":" Response (OscalBaseModel) pydantic-model","text":"

                                    Describes either recommended or an actual plan for addressing the risk.

                                    Source code in trestle/oscal/common.py
                                    class Response(OscalBaseModel):\n\"\"\"\n    Describes either recommended or an actual plan for addressing the risk.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this remediation elsewhere in this or other OSCAL instances. The locally defined UUID of the risk response can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Remediation Universally Unique Identifier',\n    )\n    lifecycle: Union[\n        constr(\n            regex=\n            r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n        ),\n        Lifecycle\n    ] = Field(\n        ...,\n        description=\n        'Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.',\n        title='Remediation Intent'\n    )\n    title: str = Field(..., description='The title for this response activity.', title='Response Title')\n    description: str = Field(\n        ..., description='A human-readable description of this response plan.', title='Response Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    origins: Optional[List[Origin]] = Field(None)\n    required_assets: Optional[List[RequiredAsset]] = Field(None, alias='required-assets')\n    tasks: Optional[List[Task]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this response plan.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.lifecycle","title":"lifecycle: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Lifecycle] pydantic-field required","text":"

                                    Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.required_assets","title":"required_assets: List[trestle.oscal.common.RequiredAsset] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.title","title":"title: str pydantic-field required","text":"

                                    The title for this response activity.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this remediation elsewhere in this or other OSCAL instances. The locally defined UUID of the risk response can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty","title":" ResponsibleParty (OscalBaseModel) pydantic-model","text":"

                                    A reference to a set of persons and/or organizations that have responsibility for performing the referenced role in the context of the containing object.

                                    Source code in trestle/oscal/common.py
                                    class ResponsibleParty(OscalBaseModel):\n\"\"\"\n    A reference to a set of persons and/or organizations that have responsibility for performing the referenced role in the context of the containing object.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    role_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ..., alias='role-id', description='A reference to a role performed by a party.', title='Responsible Role'\n    )\n    party_uuids: List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(..., alias='party-uuids')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.party_uuids","title":"party_uuids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.role_id","title":"role_id: ConstrainedStrValue pydantic-field required","text":"

                                    A reference to a role performed by a party.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole","title":" ResponsibleRole (OscalBaseModel) pydantic-model","text":"

                                    A reference to a role with responsibility for performing a function relative to the containing object, optionally associated with a set of persons and/or organizations that perform that role.

                                    Source code in trestle/oscal/common.py
                                    class ResponsibleRole(OscalBaseModel):\n\"\"\"\n    A reference to a role with responsibility for performing a function relative to the containing object, optionally associated with a set of persons and/or organizations that perform that role.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    role_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='role-id',\n        description='A human-oriented identifier reference to a role performed.',\n        title='Responsible Role ID'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    party_uuids: Optional[List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )]] = Field(\n        None, alias='party-uuids'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.party_uuids","title":"party_uuids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.role_id","title":"role_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented identifier reference to a role performed.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls","title":" ReviewedControls (OscalBaseModel) pydantic-model","text":"

                                    Identifies the controls being assessed and their control objectives.

                                    Source code in trestle/oscal/common.py
                                    class ReviewedControls(OscalBaseModel):\n\"\"\"\n    Identifies the controls being assessed and their control objectives.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None, description='A human-readable description of control objectives.', title='Control Objective Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    control_selections: List[ControlSelection] = Field(..., alias='control-selections')\n    control_objective_selections: Optional[List[ControlObjectiveSelection]] = Field(\n        None, alias='control-objective-selections'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.control_objective_selections","title":"control_objective_selections: List[trestle.oscal.common.ControlObjectiveSelection] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.control_selections","title":"control_selections: List[trestle.oscal.common.ControlSelection] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of control objectives.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision","title":" Revision (OscalBaseModel) pydantic-model","text":"

                                    An entry in a sequential list of revisions to the containing document, expected to be in reverse chronological order (i.e. latest first).

                                    Source code in trestle/oscal/common.py
                                    class Revision(OscalBaseModel):\n\"\"\"\n    An entry in a sequential list of revisions to the containing document, expected to be in reverse chronological order (i.e. latest first).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the document revision, which may be used by a tool for display and navigation.',\n        title='Document Title'\n    )\n    published: Optional[datetime] = None\n    last_modified: Optional[datetime] = Field(None, alias='last-modified')\n    version: constr(regex=r'^\\S(.*\\S)?$')\n    oscal_version: Optional[OscalVersion] = Field(None, alias='oscal-version')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.last_modified","title":"last_modified: datetime pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.oscal_version","title":"oscal_version: OscalVersion pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.published","title":"published: datetime pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.title","title":"title: str pydantic-field","text":"

                                    A name given to the document revision, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.version","title":"version: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk","title":" Risk (OscalBaseModel) pydantic-model","text":"

                                    An identified risk.

                                    Source code in trestle/oscal/common.py
                                    class Risk(OscalBaseModel):\n\"\"\"\n    An identified risk.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk elsewhere in this or other OSCAL instances. The locally defined UUID of the risk can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Risk Universally Unique Identifier',\n    )\n    title: str = Field(..., description='The title for this risk.', title='Risk Title')\n    description: str = Field(\n        ...,\n        description=\n        'A human-readable summary of the identified risk, to include a statement of how the risk impacts the system.',\n        title='Risk Description'\n    )\n    statement: str = Field(\n        ..., description='An summary of impact for how the risk affects the system.', title='Risk Statement'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    status: RiskStatus\n    origins: Optional[List[Origin]] = Field(None)\n    threat_ids: Optional[List[ThreatId]] = Field(None, alias='threat-ids')\n    characterizations: Optional[List[Characterization]] = Field(None)\n    mitigating_factors: Optional[List[MitigatingFactor]] = Field(None, alias='mitigating-factors')\n    deadline: Optional[datetime] = Field(\n        None, description='The date/time by which the risk must be resolved.', title='Risk Resolution Deadline'\n    )\n    remediations: Optional[List[Response]] = Field(None)\n    risk_log: Optional[RiskLog] = Field(\n        None, alias='risk-log', description='A log of all risk-related tasks taken.', title='Risk Log'\n    )\n    related_observations: Optional[List[RelatedObservation]] = Field(None, alias='related-observations')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.characterizations","title":"characterizations: List[trestle.oscal.common.Characterization] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.deadline","title":"deadline: datetime pydantic-field","text":"

                                    The date/time by which the risk must be resolved.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.description","title":"description: str pydantic-field required","text":"

                                    A human-readable summary of the identified risk, to include a statement of how the risk impacts the system.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.mitigating_factors","title":"mitigating_factors: List[trestle.oscal.common.MitigatingFactor] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.related_observations","title":"related_observations: List[trestle.oscal.common.RelatedObservation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.remediations","title":"remediations: List[trestle.oscal.common.Response] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.risk_log","title":"risk_log: RiskLog pydantic-field","text":"

                                    A log of all risk-related tasks taken.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.statement","title":"statement: str pydantic-field required","text":"

                                    An summary of impact for how the risk affects the system.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.status","title":"status: RiskStatus pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.threat_ids","title":"threat_ids: List[trestle.oscal.common.ThreatId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.title","title":"title: str pydantic-field required","text":"

                                    The title for this risk.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk elsewhere in this or other OSCAL instances. The locally defined UUID of the risk can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog","title":" RiskLog (OscalBaseModel) pydantic-model","text":"

                                    A log of all risk-related tasks taken.

                                    Source code in trestle/oscal/common.py
                                    class RiskLog(OscalBaseModel):\n\"\"\"\n    A log of all risk-related tasks taken.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    entries: List[Entry] = Field(...)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.entries","title":"entries: List[trestle.oscal.common.Entry] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus","title":" RiskStatus (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class RiskStatus(OscalBaseModel):\n    __root__: Union[TokenDatatype, RiskStatusValidValues] = Field(\n        ..., description='Describes the status of the associated risk.', title='Risk Status'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__root__","title":"__root__: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.RiskStatusValidValues] pydantic-field required special","text":"

                                    Describes the status of the associated risk.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues","title":" RiskStatusValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class RiskStatusValidValues(Enum):\n    open = 'open'\n    investigating = 'investigating'\n    remediating = 'remediating'\n    deviation_requested = 'deviation-requested'\n    deviation_approved = 'deviation-approved'\n    closed = 'closed'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.closed","title":"closed","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.deviation_approved","title":"deviation_approved","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.deviation_requested","title":"deviation_requested","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.investigating","title":"investigating","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.open","title":"open","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.remediating","title":"remediating","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink","title":" Rlink (OscalBaseModel) pydantic-model","text":"

                                    A URL-based pointer to an external resource with an optional hash for verification and change detection.

                                    Source code in trestle/oscal/common.py
                                    class Rlink(OscalBaseModel):\n\"\"\"\n    A URL-based pointer to an external resource with an optional hash for verification and change detection.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ..., description='A resolvable URL pointing to the referenced resource.', title='Hypertext Reference'\n    )\n    media_type: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='media-type',\n        description='A label that indicates the nature of a resource, as a data serialization or format.',\n        title='Media Type'\n    )\n    hashes: Optional[List[Hash]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.hashes","title":"hashes: List[trestle.oscal.common.Hash] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.href","title":"href: str pydantic-field required","text":"

                                    A resolvable URL pointing to the referenced resource.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.media_type","title":"media_type: ConstrainedStrValue pydantic-field","text":"

                                    A label that indicates the nature of a resource, as a data serialization or format.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role","title":" Role (OscalBaseModel) pydantic-model","text":"

                                    Defines a function, which might be assigned to a party in a specific situation.

                                    Source code in trestle/oscal/common.py
                                    class Role(OscalBaseModel):\n\"\"\"\n    Defines a function, which might be assigned to a party in a specific situation.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., description='A unique identifier for the role.', title='Role Identifier')\n    title: str = Field(\n        ...,\n        description='A name given to the role, which may be used by a tool for display and navigation.',\n        title='Role Title'\n    )\n    short_name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='short-name',\n        description='A short common name, abbreviation, or acronym for the role.',\n        title='Role Short Name'\n    )\n    description: Optional[str] = Field(\n        None, description=\"A summary of the role's purpose and associated responsibilities.\", title='Role Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.description","title":"description: str pydantic-field","text":"

                                    A summary of the role's purpose and associated responsibilities.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.id","title":"id: ConstrainedStrValue pydantic-field required","text":"

                                    A unique identifier for the role.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.short_name","title":"short_name: ConstrainedStrValue pydantic-field","text":"

                                    A short common name, abbreviation, or acronym for the role.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.title","title":"title: str pydantic-field required","text":"

                                    A name given to the role, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId","title":" RoleId (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class RoleId(OscalBaseModel):\n    __root__: TokenDatatype = Field(..., description='Reference to a role by UUID.', title='Role Identifier Reference')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__root__","title":"__root__: TokenDatatype pydantic-field required special","text":"

                                    Reference to a role by UUID.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById","title":" SelectControlById (OscalBaseModel) pydantic-model","text":"

                                    Used to select a control for inclusion/exclusion based on one or more control identifiers. A set of statement identifiers can be used to target the inclusion/exclusion to only specific control statements providing more granularity over the specific statements that are within the asessment scope.

                                    Source code in trestle/oscal/common.py
                                    class SelectControlById(OscalBaseModel):\n\"\"\"\n    Used to select a control for inclusion/exclusion based on one or more control identifiers. A set of statement identifiers can be used to target the inclusion/exclusion to only specific control statements providing more granularity over the specific statements that are within the asessment scope.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    statement_ids: Optional[List[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )]] = Field(\n        None, alias='statement-ids'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                    A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.statement_ids","title":"statement_ids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById","title":" SelectObjectiveById (OscalBaseModel) pydantic-model","text":"

                                    Used to select a control objective for inclusion/exclusion based on the control objective's identifier.

                                    Source code in trestle/oscal/common.py
                                    class SelectObjectiveById(OscalBaseModel):\n\"\"\"\n    Used to select a control objective for inclusion/exclusion based on the control objective's identifier.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    objective_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., alias='objective-id', description='Points to an assessment objective.', title='Objective ID')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.objective_id","title":"objective_id: ConstrainedStrValue pydantic-field required","text":"

                                    Points to an assessment objective.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById","title":" SelectSubjectById (OscalBaseModel) pydantic-model","text":"

                                    Identifies a set of assessment subjects to include/exclude by UUID.

                                    Source code in trestle/oscal/common.py
                                    class SelectSubjectById(OscalBaseModel):\n\"\"\"\n    Identifies a set of assessment subjects to include/exclude by UUID.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    subject_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='subject-uuid',\n        description=\n        \"A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.\",\n        title='Subject Universally Unique Identifier Reference'\n    )\n    type: Union[TokenDatatype, SelectSubjectByIdValidValues] = Field(\n        ...,\n        description='Used to indicate the type of object pointed to by the uuid-ref within a subject.',\n        title='Subject Universally Unique Identifier Reference Type'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.subject_uuid","title":"subject_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.SelectSubjectByIdValidValues] pydantic-field required","text":"

                                    Used to indicate the type of object pointed to by the uuid-ref within a subject.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues","title":" SelectSubjectByIdValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class SelectSubjectByIdValidValues(Enum):\n    component = 'component'\n    inventory_item = 'inventory-item'\n    location = 'location'\n    party = 'party'\n    user = 'user'\n    resource = 'resource'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.component","title":"component","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.inventory_item","title":"inventory_item","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.location","title":"location","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.resource","title":"resource","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.user","title":"user","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source","title":" Source (OscalBaseModel) pydantic-model","text":"

                                    Assessment subjects will be identified while conducting the referenced activity-instance.

                                    Source code in trestle/oscal/common.py
                                    class Source(OscalBaseModel):\n\"\"\"\n    Assessment subjects will be identified while conducting the referenced activity-instance.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    task_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='task-uuid',\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference (in this or other OSCAL instances) an assessment activity to be performed as part of the event. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Task Universally Unique Identifier',\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.task_uuid","title":"task_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference (in this or other OSCAL instances) an assessment activity to be performed as part of the event. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State","title":" State (Enum) ","text":"

                                    Identifies the implementation status of the control or control objective.

                                    Source code in trestle/oscal/common.py
                                    class State(Enum):\n\"\"\"\n    Identifies the implementation status of the control or control objective.\n    \"\"\"\n\n    implemented = 'implemented'\n    partial = 'partial'\n    planned = 'planned'\n    alternative = 'alternative'\n    not_applicable = 'not-applicable'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.alternative","title":"alternative","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.implemented","title":"implemented","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.not_applicable","title":"not_applicable","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.partial","title":"partial","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.planned","title":"planned","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status","title":" Status (OscalBaseModel) pydantic-model","text":"

                                    Describes the operational status of the system component.

                                    Source code in trestle/oscal/common.py
                                    class Status(OscalBaseModel):\n\"\"\"\n    Describes the operational status of the system component.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: SystemComponentOperationalStateValidValues = Field(..., description='The operational status.', title='State')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.state","title":"state: SystemComponentOperationalStateValidValues pydantic-field required","text":"

                                    The operational status.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step","title":" Step (OscalBaseModel) pydantic-model","text":"

                                    Identifies an individual step in a series of steps related to an activity, such as an assessment test or examination procedure.

                                    Source code in trestle/oscal/common.py
                                    class Step(OscalBaseModel):\n\"\"\"\n    Identifies an individual step in a series of steps related to an activity, such as an assessment test or examination procedure.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this step elsewhere in this or other OSCAL instances. The locally defined UUID of the step (in a series of steps) can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Step Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this step.', title='Step Title')\n    description: str = Field(..., description='A human-readable description of this step.', title='Step Description')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    reviewed_controls: Optional[ReviewedControls] = Field(None, alias='reviewed-controls')\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of this step.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.reviewed_controls","title":"reviewed_controls: ReviewedControls pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.title","title":"title: str pydantic-field","text":"

                                    The title for this step.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this step elsewhere in this or other OSCAL instances. The locally defined UUID of the step (in a series of steps) can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype","title":" StringDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class StringDatatype(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description=\n        'A non-empty string with leading and trailing whitespace disallowed. Whitespace is: U+9, U+10, U+32 or [ \\n\\t]+'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    A non-empty string with leading and trailing whitespace disallowed. Whitespace is: U+9, U+10, U+32 or [ ]+

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference","title":" SubjectReference (OscalBaseModel) pydantic-model","text":"

                                    A human-oriented identifier reference to a resource. Use type to indicate whether the identified resource is a component, inventory item, location, user, or something else.

                                    Source code in trestle/oscal/common.py
                                    class SubjectReference(OscalBaseModel):\n\"\"\"\n    A human-oriented identifier reference to a resource. Use type to indicate whether the identified resource is a component, inventory item, location, user, or something else.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    subject_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='subject-uuid',\n        description=\n        \"A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.\",\n        title='Subject Universally Unique Identifier Reference'\n    )\n    type: Union[TokenDatatype, SubjectReferenceValidValues] = Field(\n        ...,\n        description='Used to indicate the type of object pointed to by the uuid-ref within a subject.',\n        title='Subject Universally Unique Identifier Reference Type'\n    )\n    title: Optional[str] = Field(\n        None, description='The title or name for the referenced subject.', title='Subject Reference Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.subject_uuid","title":"subject_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.title","title":"title: str pydantic-field","text":"

                                    The title or name for the referenced subject.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.SubjectReferenceValidValues] pydantic-field required","text":"

                                    Used to indicate the type of object pointed to by the uuid-ref within a subject.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues","title":" SubjectReferenceValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class SubjectReferenceValidValues(Enum):\n    component = 'component'\n    inventory_item = 'inventory-item'\n    location = 'location'\n    party = 'party'\n    user = 'user'\n    resource = 'resource'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.component","title":"component","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.inventory_item","title":"inventory_item","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.location","title":"location","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.resource","title":"resource","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.user","title":"user","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent","title":" SystemComponent (OscalBaseModel) pydantic-model","text":"

                                    A defined component that can be part of an implemented system.

                                    Source code in trestle/oscal/common.py
                                    class SystemComponent(OscalBaseModel):\n\"\"\"\n    A defined component that can be part of an implemented system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Component Identifier',\n    )\n    type: Union[constr(regex=r'^\\S(.*\\S)?$'), SystemComponentTypeValidValues] = Field(\n        ..., description='A category describing the purpose of the component.', title='Component Type'\n    )\n    title: str = Field(..., description='A human readable name for the system component.', title='Component Title')\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description'\n    )\n    purpose: Optional[str] = Field(\n        None, description='A summary of the technological or business purpose of the component.', title='Purpose'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    status: Status = Field(..., description='Describes the operational status of the system component.', title='Status')\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    protocols: Optional[List[Protocol]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.description","title":"description: str pydantic-field required","text":"

                                    A description of the component, including information about its function.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.protocols","title":"protocols: List[trestle.oscal.common.Protocol] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.purpose","title":"purpose: str pydantic-field","text":"

                                    A summary of the technological or business purpose of the component.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.status","title":"status: Status pydantic-field required","text":"

                                    Describes the operational status of the system component.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.title","title":"title: str pydantic-field required","text":"

                                    A human readable name for the system component.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.type","title":"type: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.SystemComponentTypeValidValues] pydantic-field required","text":"

                                    A category describing the purpose of the component.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues","title":" SystemComponentOperationalStateValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class SystemComponentOperationalStateValidValues(Enum):\n    under_development = 'under-development'\n    operational = 'operational'\n    disposition = 'disposition'\n    other = 'other'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.disposition","title":"disposition","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.operational","title":"operational","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.other","title":"other","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.under_development","title":"under_development","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues","title":" SystemComponentTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class SystemComponentTypeValidValues(Enum):\n    this_system = 'this-system'\n    system = 'system'\n    interconnection = 'interconnection'\n    software = 'software'\n    hardware = 'hardware'\n    service = 'service'\n    policy = 'policy'\n    physical = 'physical'\n    process_procedure = 'process-procedure'\n    plan = 'plan'\n    guidance = 'guidance'\n    standard = 'standard'\n    validation = 'validation'\n    network = 'network'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.guidance","title":"guidance","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.hardware","title":"hardware","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.interconnection","title":"interconnection","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.network","title":"network","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.physical","title":"physical","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.plan","title":"plan","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.policy","title":"policy","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.process_procedure","title":"process_procedure","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.service","title":"service","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.software","title":"software","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.standard","title":"standard","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.system","title":"system","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.this_system","title":"this_system","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.validation","title":"validation","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId","title":" SystemId (OscalBaseModel) pydantic-model","text":"

                                    A human-oriented, globally unique identifier with cross-instance scope that can be used to reference this system identification property elsewhere in this or other OSCAL instances. When referencing an externally defined system identification, the system identification must be used in the context of the external / imported OSCAL instance (e.g., uri-reference). This string should be assigned per-subject, which means it should be consistently used to identify the same system across revisions of the document.

                                    Source code in trestle/oscal/common.py
                                    class SystemId(OscalBaseModel):\n\"\"\"\n    A human-oriented, globally unique identifier with cross-instance scope that can be used to reference this system identification property elsewhere in this or other OSCAL instances. When referencing an externally defined system identification, the system identification must be used in the context of the external / imported OSCAL instance (e.g., uri-reference). This string should be assigned per-subject, which means it should be consistently used to identify the same system across revisions of the document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    identifier_type: Optional[Union[AnyUrl, IdentifierType]] = Field(\n        None,\n        alias='identifier-type',\n        description='Identifies the identification system from which the provided identifier was assigned.',\n        title='Identification System Type'\n    )\n    id: constr(regex=r'^\\S(.*\\S)?$')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.id","title":"id: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.identifier_type","title":"identifier_type: Union[pydantic.v1.networks.AnyUrl, trestle.oscal.common.IdentifierType] pydantic-field","text":"

                                    Identifies the identification system from which the provided identifier was assigned.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser","title":" SystemUser (OscalBaseModel) pydantic-model","text":"

                                    A type of user that interacts with the system based on an associated role.

                                    Source code in trestle/oscal/common.py
                                    class SystemUser(OscalBaseModel):\n\"\"\"\n    A type of user that interacts with the system based on an associated role.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this user class elsewhere in this or other OSCAL instances. The locally defined UUID of the system user can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='User Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the user, which may be used by a tool for display and navigation.',\n        title='User Title'\n    )\n    short_name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='short-name',\n        description='A short common name, abbreviation, or acronym for the user.',\n        title='User Short Name'\n    )\n    description: Optional[str] = Field(\n        None, description=\"A summary of the user's purpose within the system.\", title='User Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    role_ids: Optional[List[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )]] = Field(\n        None, alias='role-ids'\n    )\n    authorized_privileges: Optional[List[AuthorizedPrivilege]] = Field(None, alias='authorized-privileges')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.authorized_privileges","title":"authorized_privileges: List[trestle.oscal.common.AuthorizedPrivilege] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.description","title":"description: str pydantic-field","text":"

                                    A summary of the user's purpose within the system.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.role_ids","title":"role_ids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.short_name","title":"short_name: ConstrainedStrValue pydantic-field","text":"

                                    A short common name, abbreviation, or acronym for the user.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.title","title":"title: str pydantic-field","text":"

                                    A name given to the user, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this user class elsewhere in this or other OSCAL instances. The locally defined UUID of the system user can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task","title":" Task (OscalBaseModel) pydantic-model","text":"

                                    Represents a scheduled event or milestone, which may be associated with a series of assessment actions.

                                    Source code in trestle/oscal/common.py
                                    class Task(OscalBaseModel):\n\"\"\"\n    Represents a scheduled event or milestone, which may be associated with a series of assessment actions.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this task elsewhere in this or other OSCAL instances. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Task Universally Unique Identifier',\n    )\n    type: Union[TokenDatatype, TaskValidValues] = Field(..., description='The type of task.', title='Task Type')\n    title: str = Field(..., description='The title for this task.', title='Task Title')\n    description: Optional[str] = Field(\n        None, description='A human-readable description of this task.', title='Task Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    timing: Optional[Timing] = Field(\n        None, description='The timing under which the task is intended to occur.', title='Event Timing'\n    )\n    dependencies: Optional[List[Dependency]] = Field(None)\n    tasks: Optional[List[Task]] = None\n    associated_activities: Optional[List[AssociatedActivity]] = Field(None, alias='associated-activities')\n    subjects: Optional[List[AssessmentSubject]] = Field(None)\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.associated_activities","title":"associated_activities: List[trestle.oscal.common.AssociatedActivity] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.dependencies","title":"dependencies: List[trestle.oscal.common.Dependency] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.description","title":"description: str pydantic-field","text":"

                                    A human-readable description of this task.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.timing","title":"timing: Timing pydantic-field","text":"

                                    The timing under which the task is intended to occur.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.title","title":"title: str pydantic-field required","text":"

                                    The title for this task.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.TaskValidValues] pydantic-field required","text":"

                                    The type of task.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this task elsewhere in this or other OSCAL instances. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TaskValidValues","title":" TaskValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class TaskValidValues(Enum):\n    milestone = 'milestone'\n    action = 'action'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TaskValidValues.action","title":"action","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TaskValidValues.milestone","title":"milestone","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber","title":" TelephoneNumber (OscalBaseModel) pydantic-model","text":"

                                    A telephone service number as defined by ITU-T E.164.

                                    Source code in trestle/oscal/common.py
                                    class TelephoneNumber(OscalBaseModel):\n\"\"\"\n    A telephone service number as defined by ITU-T E.164.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: Optional[Union[StringDatatype, TelephoneTypeValidValues]] = Field(\n        None, description='Indicates the type of phone number.', title='type flag'\n    )\n    number: constr(regex=r'^\\S(.*\\S)?$')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.number","title":"number: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.type","title":"type: Union[trestle.oscal.common.StringDatatype, trestle.oscal.common.TelephoneTypeValidValues] pydantic-field","text":"

                                    Indicates the type of phone number.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues","title":" TelephoneTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class TelephoneTypeValidValues(Enum):\n    home = 'home'\n    office = 'office'\n    mobile = 'mobile'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues.home","title":"home","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues.mobile","title":"mobile","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues.office","title":"office","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test","title":" Test (OscalBaseModel) pydantic-model","text":"

                                    A test expression which is expected to be evaluated by a tool.

                                    Source code in trestle/oscal/common.py
                                    class Test(OscalBaseModel):\n\"\"\"\n    A test expression which is expected to be evaluated by a tool.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    expression: constr(\n        regex=r'^\\S(.*\\S)?$'\n    ) = Field(..., description='A formal (executable) expression of a constraint.', title='Constraint test')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.expression","title":"expression: ConstrainedStrValue pydantic-field required","text":"

                                    A formal (executable) expression of a constraint.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId","title":" ThreatId (OscalBaseModel) pydantic-model","text":"

                                    A pointer, by ID, to an externally-defined threat.

                                    Source code in trestle/oscal/common.py
                                    class ThreatId(OscalBaseModel):\n\"\"\"\n    A pointer, by ID, to an externally-defined threat.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    system: Union[URIDatatype, ThreatIdValidValues] = Field(\n        ..., description='Specifies the source of the threat information.', title='Threat Type Identification System'\n    )\n    href: Optional[str] = Field(\n        None,\n        description='An optional location for the threat data, from which this ID originates.',\n        title='Threat Information Resource Reference'\n    )\n    id: AnyUrl\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.href","title":"href: str pydantic-field","text":"

                                    An optional location for the threat data, from which this ID originates.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.id","title":"id: AnyUrl pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.system","title":"system: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.ThreatIdValidValues] pydantic-field required","text":"

                                    Specifies the source of the threat information.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatIdValidValues","title":" ThreatIdValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class ThreatIdValidValues(Enum):\n    http___fedramp_gov = 'http://fedramp.gov'\n    http___fedramp_gov_ns_oscal = 'http://fedramp.gov/ns/oscal'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatIdValidValues.http___fedramp_gov","title":"http___fedramp_gov","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatIdValidValues.http___fedramp_gov_ns_oscal","title":"http___fedramp_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues","title":" TimeUnitValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                    class TimeUnitValidValues(Enum):\n    seconds = 'seconds'\n    minutes = 'minutes'\n    hours = 'hours'\n    days = 'days'\n    months = 'months'\n    years = 'years'\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.days","title":"days","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.hours","title":"hours","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.minutes","title":"minutes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.months","title":"months","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.seconds","title":"seconds","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.years","title":"years","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing","title":" Timing (OscalBaseModel) pydantic-model","text":"

                                    The timing under which the task is intended to occur.

                                    Source code in trestle/oscal/common.py
                                    class Timing(OscalBaseModel):\n\"\"\"\n    The timing under which the task is intended to occur.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    on_date: Optional[OnDate] = Field(\n        None,\n        alias='on-date',\n        description='The task is intended to occur on the specified date.',\n        title='On Date Condition'\n    )\n    within_date_range: Optional[WithinDateRange] = Field(\n        None,\n        alias='within-date-range',\n        description='The task is intended to occur within the specified date range.',\n        title='On Date Range Condition'\n    )\n    at_frequency: Optional[AtFrequency] = Field(\n        None,\n        alias='at-frequency',\n        description='The task is intended to occur at the specified frequency.',\n        title='Frequency Condition'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.at_frequency","title":"at_frequency: AtFrequency pydantic-field","text":"

                                    The task is intended to occur at the specified frequency.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.on_date","title":"on_date: OnDate pydantic-field","text":"

                                    The task is intended to occur on the specified date.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.within_date_range","title":"within_date_range: WithinDateRange pydantic-field","text":"

                                    The task is intended to occur within the specified date range.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype","title":" TokenDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class TokenDatatype(OscalBaseModel):\n    __root__: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        'A non-colonized name as defined by XML Schema Part 2: Datatypes Second Edition. https://www.w3.org/TR/xmlschema11-2/#NCName.'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    A non-colonized name as defined by XML Schema Part 2: Datatypes Second Edition. https://www.w3.org/TR/xmlschema11-2/#NCName.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype","title":" URIDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class URIDatatype(OscalBaseModel):\n    __root__: AnyUrl = Field(..., description='A universal resource identifier (URI) formatted according to RFC3986.')\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__root__","title":"__root__: AnyUrl pydantic-field required special","text":"

                                    A universal resource identifier (URI) formatted according to RFC3986.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype","title":" URIReferenceDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class URIReferenceDatatype(OscalBaseModel):\n    __root__: str = Field(\n        ...,\n        description=\n        'A URI Reference, either a URI or a relative-reference, formatted according to section 4.1 of RFC3986.'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__root__","title":"__root__: str pydantic-field required special","text":"

                                    A URI Reference, either a URI or a relative-reference, formatted according to section 4.1 of RFC3986.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype","title":" UUIDDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class UUIDDatatype(OscalBaseModel):\n    __root__: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(..., description=\"A type 4 ('random' or 'pseudorandom') or type 5 UUID per RFC 4122.\")\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    A type 4 ('random' or 'pseudorandom') or type 5 UUID per RFC 4122.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent","title":" UsesComponent (OscalBaseModel) pydantic-model","text":"

                                    The set of components that are used by the assessment platform.

                                    Source code in trestle/oscal/common.py
                                    class UsesComponent(OscalBaseModel):\n\"\"\"\n    The set of components that are used by the assessment platform.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description=\n        'A machine-oriented identifier reference to a component that is implemented as part of an inventory item.',\n        title='Component Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a component that is implemented as part of an inventory item.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version","title":" Version (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                    class Version(OscalBaseModel):\n    __root__: StringDatatype = Field(\n        ...,\n        description=\n        'Used to distinguish a specific revision of an OSCAL document from other previous and future versions.',\n        title='Document Version'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                    Used to distinguish a specific revision of an OSCAL document from other previous and future versions.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange","title":" WithinDateRange (OscalBaseModel) pydantic-model","text":"

                                    The task is intended to occur within the specified date range.

                                    Source code in trestle/oscal/common.py
                                    class WithinDateRange(OscalBaseModel):\n\"\"\"\n    The task is intended to occur within the specified date range.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    start: datetime = Field(\n        ..., description='The task must occur on or after the specified date.', title='Start Date Condition'\n    )\n    end: datetime = Field(\n        ..., description='The task must occur on or before the specified date.', title='End Date Condition'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.end","title":"end: datetime pydantic-field required","text":"

                                    The task must occur on or before the specified date.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.start","title":"start: datetime pydantic-field required","text":"

                                    The task must occur on or after the specified date.

                                    "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/","title":"component","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component","title":"trestle.oscal.component","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability","title":" Capability (OscalBaseModel) pydantic-model","text":"

                                    A grouping of other components and/or capabilities.

                                    Source code in trestle/oscal/component.py
                                    class Capability(OscalBaseModel):\n\"\"\"\n    A grouping of other components and/or capabilities.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given capability.',\n                     title='Capability Identifier'\n                 )\n    name: constr(regex=r'^\\S(.*\\S)?$'\n                 ) = Field(..., description=\"The capability's human-readable name.\", title='Capability Name')\n    description: str = Field(..., description='A summary of the capability.', title='Capability Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    incorporates_components: Optional[List[IncorporatesComponent]] = Field(None, alias='incorporates-components')\n    control_implementations: Optional[List[ControlImplementation]] = Field(None, alias='control-implementations')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.control_implementations","title":"control_implementations: List[trestle.oscal.component.ControlImplementation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.description","title":"description: str pydantic-field required","text":"

                                    A summary of the capability.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.incorporates_components","title":"incorporates_components: List[trestle.oscal.component.IncorporatesComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                    The capability's human-readable name.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    Provides a globally unique means to identify a given capability.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition","title":" ComponentDefinition (OscalBaseModel) pydantic-model","text":"

                                    A collection of component descriptions, which may optionally be grouped by capability.

                                    Source code in trestle/oscal/component.py
                                    class ComponentDefinition(OscalBaseModel):\n\"\"\"\n    A collection of component descriptions, which may optionally be grouped by capability.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given component definition instance.',\n                     title='Component Definition Universally Unique Identifier'\n                 )\n    metadata: common.Metadata\n    import_component_definitions: Optional[List[ImportComponentDefinition]] = Field(\n        None, alias='import-component-definitions'\n    )\n    components: Optional[List[DefinedComponent]] = Field(None)\n    capabilities: Optional[List[Capability]] = Field(None)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.capabilities","title":"capabilities: List[trestle.oscal.component.Capability] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.components","title":"components: List[trestle.oscal.component.DefinedComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.import_component_definitions","title":"import_component_definitions: List[trestle.oscal.component.ImportComponentDefinition] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    Provides a globally unique means to identify a given component definition instance.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation","title":" ControlImplementation (OscalBaseModel) pydantic-model","text":"

                                    Defines how the component or capability supports a set of controls.

                                    Source code in trestle/oscal/component.py
                                    class ControlImplementation(OscalBaseModel):\n\"\"\"\n    Defines how the component or capability supports a set of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'Provides a means to identify a set of control implementations that are supported by a given component or capability.',\n        title='Control Implementation Set Identifier'\n    )\n    source: str = Field(\n        ...,\n        description=\n        'A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.',\n        title='Source Resource Reference'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'A description of how the specified set of controls are implemented for the containing component or capability.',\n        title='Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    implemented_requirements: List[ImplementedRequirement] = Field(..., alias='implemented-requirements')\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.description","title":"description: str pydantic-field required","text":"

                                    A description of how the specified set of controls are implemented for the containing component or capability.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.implemented_requirements","title":"implemented_requirements: List[trestle.oscal.component.ImplementedRequirement] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.set_parameters","title":"set_parameters: List[trestle.oscal.component.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.source","title":"source: str pydantic-field required","text":"

                                    A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    Provides a means to identify a set of control implementations that are supported by a given component or capability.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent","title":" DefinedComponent (OscalBaseModel) pydantic-model","text":"

                                    A defined component that can be part of an implemented system.

                                    Source code in trestle/oscal/component.py
                                    class DefinedComponent(OscalBaseModel):\n\"\"\"\n    A defined component that can be part of an implemented system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given component.',\n                     title='Component Identifier'\n                 )\n    type: Union[constr(regex=r'^\\S(.*\\S)?$'), DefinedComponentTypeValidValues] = Field(\n        ..., description='A category describing the purpose of the component.', title='Component Type'\n    )\n    title: str = Field(..., description='A human readable name for the component.', title='Component Title')\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description'\n    )\n    purpose: Optional[str] = Field(\n        None, description='A summary of the technological or business purpose of the component.', title='Purpose'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    protocols: Optional[List[common.Protocol]] = Field(None)\n    control_implementations: Optional[List[ControlImplementation]] = Field(None, alias='control-implementations')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.control_implementations","title":"control_implementations: List[trestle.oscal.component.ControlImplementation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.description","title":"description: str pydantic-field required","text":"

                                    A description of the component, including information about its function.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.protocols","title":"protocols: List[trestle.oscal.common.Protocol] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.purpose","title":"purpose: str pydantic-field","text":"

                                    A summary of the technological or business purpose of the component.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.title","title":"title: str pydantic-field required","text":"

                                    A human readable name for the component.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.type","title":"type: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.component.DefinedComponentTypeValidValues] pydantic-field required","text":"

                                    A category describing the purpose of the component.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    Provides a globally unique means to identify a given component.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues","title":" DefinedComponentTypeValidValues (Enum) ","text":"Source code in trestle/oscal/component.py
                                    class DefinedComponentTypeValidValues(Enum):\n    interconnection = 'interconnection'\n    software = 'software'\n    hardware = 'hardware'\n    service = 'service'\n    policy = 'policy'\n    physical = 'physical'\n    process_procedure = 'process-procedure'\n    plan = 'plan'\n    guidance = 'guidance'\n    standard = 'standard'\n    validation = 'validation'\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.guidance","title":"guidance","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.hardware","title":"hardware","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.interconnection","title":"interconnection","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.physical","title":"physical","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.plan","title":"plan","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.policy","title":"policy","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.process_procedure","title":"process_procedure","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.service","title":"service","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.software","title":"software","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.standard","title":"standard","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.validation","title":"validation","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement","title":" ImplementedRequirement (OscalBaseModel) pydantic-model","text":"

                                    Describes how the containing component or capability implements an individual control.

                                    Source code in trestle/oscal/component.py
                                    class ImplementedRequirement(OscalBaseModel):\n\"\"\"\n    Describes how the containing component or capability implements an individual control.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description='Provides a globally unique means to identify a given control implementation by a component.',\n        title='Control Implementation Identifier'\n    )\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'A suggestion from the supplier (e.g., component vendor or author) for how the specified control may be implemented if the containing component or capability is instantiated in a system security plan.',\n        title='Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    statements: Optional[List[Statement]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                    A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.description","title":"description: str pydantic-field required","text":"

                                    A suggestion from the supplier (e.g., component vendor or author) for how the specified control may be implemented if the containing component or capability is instantiated in a system security plan.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.set_parameters","title":"set_parameters: List[trestle.oscal.component.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.statements","title":"statements: List[trestle.oscal.component.Statement] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    Provides a globally unique means to identify a given control implementation by a component.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition","title":" ImportComponentDefinition (OscalBaseModel) pydantic-model","text":"

                                    Loads a component definition from another resource.

                                    Source code in trestle/oscal/component.py
                                    class ImportComponentDefinition(OscalBaseModel):\n\"\"\"\n    Loads a component definition from another resource.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description=\n        'A link to a resource that defines a set of components and/or capabilities to import into this collection.',\n        title='Hyperlink Reference'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.href","title":"href: str pydantic-field required","text":"

                                    A link to a resource that defines a set of components and/or capabilities to import into this collection.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent","title":" IncorporatesComponent (OscalBaseModel) pydantic-model","text":"

                                    The collection of components comprising this capability.

                                    Source code in trestle/oscal/component.py
                                    class IncorporatesComponent(OscalBaseModel):\n\"\"\"\n    The collection of components comprising this capability.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description='A machine-oriented identifier reference to a component.',\n        title='Component Reference'\n    )\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a component.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.description","title":"description: str pydantic-field required","text":"

                                    A description of the component, including information about its function.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/component.py
                                    class Model(OscalBaseModel):\n    component_definition: ComponentDefinition = Field(..., alias='component-definition')\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.component_definition","title":"component_definition: ComponentDefinition pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter","title":" SetParameter (OscalBaseModel) pydantic-model","text":"

                                    Identifies the parameter that will be set by the enclosed value.

                                    Source code in trestle/oscal/component.py
                                    class SetParameter(OscalBaseModel):\n\"\"\"\n    Identifies the parameter that will be set by the enclosed value.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    param_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='param-id',\n        description=\n        \"A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.\",\n        title='Parameter ID'\n    )\n    values: List[constr(regex=r'^\\S(.*\\S)?$')] = Field(...)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement","title":" Statement (OscalBaseModel) pydantic-model","text":"

                                    Identifies which statements within a control are addressed.

                                    Source code in trestle/oscal/component.py
                                    class Statement(OscalBaseModel):\n\"\"\"\n    Identifies which statements within a control are addressed.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    statement_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='statement-id',\n        description='A human-oriented identifier reference to a control statement.',\n        title='Control Statement Reference'\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).',\n        title='Control Statement Reference Universally Unique Identifier'\n    )\n    description: str = Field(\n        ...,\n        description='A summary of how the containing control statement is implemented by the component or capability.',\n        title='Statement Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.description","title":"description: str pydantic-field required","text":"

                                    A summary of how the containing control statement is implemented by the component or capability.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.statement_id","title":"statement_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented identifier reference to a control statement.

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).

                                    "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.poam/","title":"poam","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam","title":"trestle.oscal.poam","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions","title":" LocalDefinitions (OscalBaseModel) pydantic-model","text":"

                                    Allows components, and inventory-items to be defined within the POA&M for circumstances where no OSCAL-based SSP exists, or is not delivered with the POA&M.

                                    Source code in trestle/oscal/poam.py
                                    class LocalDefinitions(OscalBaseModel):\n\"\"\"\n    Allows components, and inventory-items to be defined within the POA&M for circumstances where no OSCAL-based SSP exists, or is not delivered with the POA&M.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[common.SystemComponent]] = Field(None)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    assessment_assets: Optional[common.AssessmentAssets] = Field(None, alias='assessment-assets')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.assessment_assets","title":"assessment_assets: AssessmentAssets pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/poam.py
                                    class Model(OscalBaseModel):\n    plan_of_action_and_milestones: PlanOfActionAndMilestones = Field(..., alias='plan-of-action-and-milestones')\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.plan_of_action_and_milestones","title":"plan_of_action_and_milestones: PlanOfActionAndMilestones pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination","title":" Origination (OscalBaseModel) pydantic-model","text":"

                                    Identifies the source of the finding, such as a tool or person.

                                    Source code in trestle/oscal/poam.py
                                    class Origination(OscalBaseModel):\n\"\"\"\n    Identifies the source of the finding, such as a tool or person.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    actors: List[common.OriginActor] = Field(...)\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.actors","title":"actors: List[trestle.oscal.common.OriginActor] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones","title":" PlanOfActionAndMilestones (OscalBaseModel) pydantic-model","text":"

                                    A plan of action and milestones which identifies initial and residual risks, deviations, and disposition, such as those required by FedRAMP.

                                    Source code in trestle/oscal/poam.py
                                    class PlanOfActionAndMilestones(OscalBaseModel):\n\"\"\"\n    A plan of action and milestones which identifies initial and residual risks, deviations, and disposition, such as those required by FedRAMP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with instancescope that can be used to reference this POA&M instance in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='POA&M Universally Unique Identifier'\n    )\n    metadata: common.Metadata\n    import_ssp: Optional[common.ImportSsp] = Field(None, alias='import-ssp')\n    system_id: Optional[common.SystemId] = Field(None, alias='system-id')\n    local_definitions: Optional[LocalDefinitions] = Field(None, alias='local-definitions')\n    observations: Optional[List[common.Observation]] = Field(None)\n    risks: Optional[List[common.Risk]] = Field(None)\n    findings: Optional[List[common.Finding]] = Field(None)\n    poam_items: List[PoamItem] = Field(..., alias='poam-items')\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.findings","title":"findings: List[trestle.oscal.common.Finding] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.import_ssp","title":"import_ssp: ImportSsp pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.local_definitions","title":"local_definitions: LocalDefinitions pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.observations","title":"observations: List[trestle.oscal.common.Observation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.poam_items","title":"poam_items: List[trestle.oscal.poam.PoamItem] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.risks","title":"risks: List[trestle.oscal.common.Risk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.system_id","title":"system_id: SystemId pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with instancescope that can be used to reference this POA&M instance in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem","title":" PoamItem (OscalBaseModel) pydantic-model","text":"

                                    Describes an individual POA&M item.

                                    Source code in trestle/oscal/poam.py
                                    class PoamItem(OscalBaseModel):\n\"\"\"\n    Describes an individual POA&M item.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with instance scope that can be used to reference this POA&M item entry in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='POA&M Item Universally Unique Identifier'\n    )\n    title: str = Field(..., description='The title or name for this POA&M item .', title='POA&M Item Title')\n    description: str = Field(\n        ..., description='A human-readable description of POA&M item.', title='POA&M Item Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    related_findings: Optional[List[RelatedFinding]] = Field(None, alias='related-findings')\n    related_observations: Optional[List[common.RelatedObservation]] = Field(None, alias='related-observations')\n    related_risks: Optional[List[common.RelatedRisk]] = Field(None, alias='related-risks')\n    remarks: Optional[str] = None\n    origins: Optional[List[Origination]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.description","title":"description: str pydantic-field required","text":"

                                    A human-readable description of POA&M item.

                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.origins","title":"origins: List[trestle.oscal.poam.Origination] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.related_findings","title":"related_findings: List[trestle.oscal.poam.RelatedFinding] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.related_observations","title":"related_observations: List[trestle.oscal.common.RelatedObservation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.related_risks","title":"related_risks: List[trestle.oscal.common.RelatedRisk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.title","title":"title: str pydantic-field required","text":"

                                    The title or name for this POA&M item .

                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented, globally unique identifier with instance scope that can be used to reference this POA&M item entry in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding","title":" RelatedFinding (OscalBaseModel) pydantic-model","text":"

                                    Relates the finding to referenced finding(s).

                                    Source code in trestle/oscal/poam.py
                                    class RelatedFinding(OscalBaseModel):\n\"\"\"\n    Relates the finding to referenced finding(s).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    finding_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='finding-uuid',\n        description='A machine-oriented identifier reference to a finding defined in the list of findings.',\n        title='Finding Universally Unique Identifier Reference'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.finding_uuid","title":"finding_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to a finding defined in the list of findings.

                                    "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/","title":"profile","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile","title":"trestle.oscal.profile","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add","title":" Add (OscalBaseModel) pydantic-model","text":"

                                    Specifies contents to be added into controls, in resolution.

                                    Source code in trestle/oscal/profile.py
                                    class Add(OscalBaseModel):\n\"\"\"\n    Specifies contents to be added into controls, in resolution.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    position: Optional[PositionValidValues] = Field(\n        None,\n        description='Where to add the new content with respect to the targeted element (beside it or inside it).',\n        title='Position'\n    )\n    by_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, alias='by-id', description='Target location of the addition.', title='Reference by ID'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the control, which may be used by a tool for display and navigation.',\n        title='Title Change'\n    )\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.by_id","title":"by_id: ConstrainedStrValue pydantic-field","text":"

                                    Target location of the addition.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.position","title":"position: PositionValidValues pydantic-field","text":"

                                    Where to add the new content with respect to the targeted element (beside it or inside it).

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.title","title":"title: str pydantic-field","text":"

                                    A name given to the control, which may be used by a tool for display and navigation.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter","title":" Alter (OscalBaseModel) pydantic-model","text":"

                                    Specifies changes to be made to an included control when a profile is resolved.

                                    Source code in trestle/oscal/profile.py
                                    class Alter(OscalBaseModel):\n\"\"\"\n    Specifies changes to be made to an included control when a profile is resolved.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    removes: Optional[List[Remove]] = Field(None)\n    adds: Optional[List[Add]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.adds","title":"adds: List[trestle.oscal.profile.Add] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                    A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.removes","title":"removes: List[trestle.oscal.profile.Remove] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype","title":" BooleanDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/profile.py
                                    class BooleanDatatype(OscalBaseModel):\n    __root__: bool = Field(..., description='A binary value that is either: true or false.')\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__root__","title":"__root__: bool pydantic-field required special","text":"

                                    A binary value that is either: true or false.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues","title":" CombinationMethodValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                    class CombinationMethodValidValues(Enum):\n    use_first = 'use-first'\n    merge = 'merge'\n    keep = 'keep'\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues.keep","title":"keep","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues.merge","title":"merge","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues.use_first","title":"use_first","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine","title":" Combine (OscalBaseModel) pydantic-model","text":"

                                    A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).

                                    Source code in trestle/oscal/profile.py
                                    class Combine(OscalBaseModel):\n\"\"\"\n    A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    method: Optional[CombinationMethodValidValues] = Field(\n        None, description='Declare how clashing controls should be handled.', title='Combination Method'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.method","title":"method: CombinationMethodValidValues pydantic-field","text":"

                                    Declare how clashing controls should be handled.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom","title":" Custom (OscalBaseModel) pydantic-model","text":"

                                    Provides an alternate grouping structure that selected controls will be placed in.

                                    Source code in trestle/oscal/profile.py
                                    class Custom(OscalBaseModel):\n\"\"\"\n    Provides an alternate grouping structure that selected controls will be placed in.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    groups: Optional[List[Group]] = Field(None)\n    insert_controls: Optional[List[InsertControls]] = Field(None, alias='insert-controls')\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.groups","title":"groups: List[trestle.oscal.profile.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.insert_controls","title":"insert_controls: List[trestle.oscal.profile.InsertControls] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group","title":" Group (OscalBaseModel) pydantic-model","text":"

                                    A group of (selected) controls or of groups of controls.

                                    Source code in trestle/oscal/profile.py
                                    class Group(OscalBaseModel):\n\"\"\"\n    A group of (selected) controls or of groups of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, description='Identifies the group.', title='Group Identifier'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a sub-type or characterization of the group.',\n        title='Group Class'\n    )\n    title: str = Field(..., description='A name to be given to the group for use in display.', title='Group Title')\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n    groups: Optional[List[Group]] = None\n    insert_controls: Optional[List[InsertControls]] = Field(None, alias='insert-controls')\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    A textual label that provides a sub-type or characterization of the group.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.groups","title":"groups: List[trestle.oscal.profile.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.id","title":"id: ConstrainedStrValue pydantic-field","text":"

                                    Identifies the group.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.insert_controls","title":"insert_controls: List[trestle.oscal.profile.InsertControls] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.title","title":"title: str pydantic-field required","text":"

                                    A name to be given to the group for use in display.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import","title":" Import (OscalBaseModel) pydantic-model","text":"

                                    Designates a referenced source catalog or profile that provides a source of control information for use in creating a new overlay or baseline.

                                    Source code in trestle/oscal/profile.py
                                    class Import(OscalBaseModel):\n\"\"\"\n    Designates a referenced source catalog or profile that provides a source of control information for use in creating a new overlay or baseline.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description='A resolvable URL reference to the base catalog or profile that this profile is tailoring.',\n        title='Catalog or Profile Reference'\n    )\n    include_all: Optional[common.IncludeAll] = Field(None, alias='include-all')\n    include_controls: Optional[List[SelectControl]] = Field(None, alias='include-controls')\n    exclude_controls: Optional[List[SelectControl]] = Field(None, alias='exclude-controls')\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.exclude_controls","title":"exclude_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.href","title":"href: str pydantic-field required","text":"

                                    A resolvable URL reference to the base catalog or profile that this profile is tailoring.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.include_controls","title":"include_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls","title":" InsertControls (OscalBaseModel) pydantic-model","text":"

                                    Specifies which controls to use in the containing context.

                                    Source code in trestle/oscal/profile.py
                                    class InsertControls(OscalBaseModel):\n\"\"\"\n    Specifies which controls to use in the containing context.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    order: Optional[OrderValidValues] = Field(\n        None, description='A designation of how a selection of controls in a profile is to be ordered.', title='Order'\n    )\n    include_all: Optional[common.IncludeAll] = Field(None, alias='include-all')\n    include_controls: Optional[List[SelectControl]] = Field(None, alias='include-controls')\n    exclude_controls: Optional[List[SelectControl]] = Field(None, alias='exclude-controls')\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.exclude_controls","title":"exclude_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.include_controls","title":"include_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.order","title":"order: OrderValidValues pydantic-field","text":"

                                    A designation of how a selection of controls in a profile is to be ordered.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues","title":" ItemNameValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                    class ItemNameValidValues(Enum):\n    param = 'param'\n    prop = 'prop'\n    link = 'link'\n    part = 'part'\n    mapping = 'mapping'\n    map = 'map'\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.link","title":"link","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.map","title":"map","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.mapping","title":"mapping","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.param","title":"param","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.part","title":"part","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.prop","title":"prop","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching","title":" Matching (OscalBaseModel) pydantic-model","text":"

                                    Selecting a set of controls by matching their IDs with a wildcard pattern.

                                    Source code in trestle/oscal/profile.py
                                    class Matching(OscalBaseModel):\n\"\"\"\n    Selecting a set of controls by matching their IDs with a wildcard pattern.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    pattern: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='A glob expression matching the IDs of one or more controls to be selected.', title='Pattern'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.pattern","title":"pattern: ConstrainedStrValue pydantic-field","text":"

                                    A glob expression matching the IDs of one or more controls to be selected.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge","title":" Merge (OscalBaseModel) pydantic-model","text":"

                                    Provides structuring directives that instruct how controls are organized after profile resolution.

                                    Source code in trestle/oscal/profile.py
                                    class Merge(OscalBaseModel):\n\"\"\"\n    Provides structuring directives that instruct how controls are organized after profile resolution.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    combine: Optional[Combine] = Field(\n        None,\n        description=\n        'A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).',\n        title='Combination Rule'\n    )\n    flat: Optional[Dict[str, Any]] = Field(\n        None, description='Directs that controls appear without any grouping structure.', title='Flat Without Grouping'\n    )\n    as_is: Optional[BooleanDatatype] = Field(\n        None,\n        alias='as-is',\n        description=\n        'Indicates that the controls selected should retain their original grouping as defined in the import source.',\n        title='Group As-Is'\n    )\n    custom: Optional[Custom] = Field(\n        None,\n        description='Provides an alternate grouping structure that selected controls will be placed in.',\n        title='Custom Grouping'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.as_is","title":"as_is: BooleanDatatype pydantic-field","text":"

                                    Indicates that the controls selected should retain their original grouping as defined in the import source.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.combine","title":"combine: Combine pydantic-field","text":"

                                    A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.custom","title":"custom: Custom pydantic-field","text":"

                                    Provides an alternate grouping structure that selected controls will be placed in.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.flat","title":"flat: Dict[str, Any] pydantic-field","text":"

                                    Directs that controls appear without any grouping structure.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/profile.py
                                    class Model(OscalBaseModel):\n    profile: Profile\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.profile","title":"profile: Profile pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify","title":" Modify (OscalBaseModel) pydantic-model","text":"

                                    Set parameters or amend controls in resolution.

                                    Source code in trestle/oscal/profile.py
                                    class Modify(OscalBaseModel):\n\"\"\"\n    Set parameters or amend controls in resolution.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    alters: Optional[List[Alter]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.alters","title":"alters: List[trestle.oscal.profile.Alter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.set_parameters","title":"set_parameters: List[trestle.oscal.profile.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues","title":" OrderValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                    class OrderValidValues(Enum):\n    keep = 'keep'\n    ascending = 'ascending'\n    descending = 'descending'\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues.ascending","title":"ascending","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues.descending","title":"descending","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues.keep","title":"keep","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues","title":" PositionValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                    class PositionValidValues(Enum):\n    before = 'before'\n    after = 'after'\n    starting = 'starting'\n    ending = 'ending'\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.after","title":"after","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.before","title":"before","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.ending","title":"ending","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.starting","title":"starting","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile","title":" Profile (OscalBaseModel) pydantic-model","text":"

                                    Each OSCAL profile is defined by a profile element.

                                    Source code in trestle/oscal/profile.py
                                    class Profile(OscalBaseModel):\n\"\"\"\n    Each OSCAL profile is defined by a profile element.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given profile instance.',\n                     title='Profile Universally Unique Identifier'\n                 )\n    metadata: common.Metadata\n    imports: List[Import] = Field(...)\n    merge: Optional[Merge] = None\n    modify: Optional[Modify] = None\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.imports","title":"imports: List[trestle.oscal.profile.Import] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.merge","title":"merge: Merge pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.modify","title":"modify: Modify pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    Provides a globally unique means to identify a given profile instance.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove","title":" Remove (OscalBaseModel) pydantic-model","text":"

                                    Specifies objects to be removed from a control based on specific aspects of the object that must all match.

                                    Source code in trestle/oscal/profile.py
                                    class Remove(OscalBaseModel):\n\"\"\"\n    Specifies objects to be removed from a control based on specific aspects of the object that must all match.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    by_name: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='by-name',\n        description='Identify items remove by matching their assigned name.',\n        title='Reference by (assigned) name'\n    )\n    by_class: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='by-class',\n        description='Identify items to remove by matching their class.',\n        title='Reference by class'\n    )\n    by_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, alias='by-id', description='Identify items to remove indicated by their id.', title='Reference by ID'\n    )\n    by_item_name: Optional[ItemNameValidValues] = Field(\n        None,\n        alias='by-item-name',\n        description=\"Identify items to remove by the name of the item's information object name, e.g. title or prop.\",\n        title='Item Name Reference'\n    )\n    by_ns: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='by-ns',\n        description=\"Identify items to remove by the item's ns, which is the namespace associated with a part, or prop.\",\n        title='Item Namespace Reference'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_class","title":"by_class: ConstrainedStrValue pydantic-field","text":"

                                    Identify items to remove by matching their class.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_id","title":"by_id: ConstrainedStrValue pydantic-field","text":"

                                    Identify items to remove indicated by their id.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_item_name","title":"by_item_name: ItemNameValidValues pydantic-field","text":"

                                    Identify items to remove by the name of the item's information object name, e.g. title or prop.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_name","title":"by_name: ConstrainedStrValue pydantic-field","text":"

                                    Identify items remove by matching their assigned name.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_ns","title":"by_ns: ConstrainedStrValue pydantic-field","text":"

                                    Identify items to remove by the item's ns, which is the namespace associated with a part, or prop.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl","title":" SelectControl (OscalBaseModel) pydantic-model","text":"

                                    Select a control or controls from an imported control set.

                                    Source code in trestle/oscal/profile.py
                                    class SelectControl(OscalBaseModel):\n\"\"\"\n    Select a control or controls from an imported control set.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    with_child_controls: Optional[WithChildControlsValidValues] = Field(\n        None,\n        alias='with-child-controls',\n        description='When a control is included, whether its child (dependent) controls are also included.',\n        title='Include Contained Controls with Control'\n    )\n    with_ids: Optional[List[WithId]] = Field(None, alias='with-ids')\n    matching: Optional[List[Matching]] = Field(None)\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.matching","title":"matching: List[trestle.oscal.profile.Matching] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.with_child_controls","title":"with_child_controls: WithChildControlsValidValues pydantic-field","text":"

                                    When a control is included, whether its child (dependent) controls are also included.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.with_ids","title":"with_ids: List[trestle.oscal.profile.WithId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter","title":" SetParameter (OscalBaseModel) pydantic-model","text":"

                                    A parameter setting, to be propagated to points of insertion.

                                    Source code in trestle/oscal/profile.py
                                    class SetParameter(OscalBaseModel):\n\"\"\"\n    A parameter setting, to be propagated to points of insertion.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    param_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., alias='param-id', description='An identifier for the parameter.', title='Parameter ID')\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a characterization of the parameter.',\n        title='Parameter Class'\n    )\n    depends_on: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='depends-on',\n        description=\n        '**(deprecated)** Another parameter invoking this one. This construct has been deprecated and should not be used.',\n        title='Depends On'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    label: Optional[str] = Field(\n        None,\n        description=\n        'A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.',\n        title='Parameter Label'\n    )\n    usage: Optional[str] = Field(\n        None, description='Describes the purpose and use of a parameter.', title='Parameter Usage Description'\n    )\n    constraints: Optional[List[common.ParameterConstraint]] = Field(None)\n    guidelines: Optional[List[common.ParameterGuideline]] = Field(None)\n    values: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None)\n    select: Optional[common.ParameterSelection] = None\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                    A textual label that provides a characterization of the parameter.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.constraints","title":"constraints: List[trestle.oscal.common.ParameterConstraint] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.depends_on","title":"depends_on: ConstrainedStrValue pydantic-field","text":"

                                    (deprecated) Another parameter invoking this one. This construct has been deprecated and should not be used.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.guidelines","title":"guidelines: List[trestle.oscal.common.ParameterGuideline] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.label","title":"label: str pydantic-field","text":"

                                    A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                    An identifier for the parameter.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.select","title":"select: ParameterSelection pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.usage","title":"usage: str pydantic-field","text":"

                                    Describes the purpose and use of a parameter.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithChildControlsValidValues","title":" WithChildControlsValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                    class WithChildControlsValidValues(Enum):\n    yes = 'yes'\n    no = 'no'\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithChildControlsValidValues.no","title":"no","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithChildControlsValidValues.yes","title":"yes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId","title":" WithId (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/profile.py
                                    class WithId(OscalBaseModel):\n    __root__: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ..., description='Selecting a control by its ID given as a literal.', title='Match Controls by Identifier'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    Selecting a control by its ID given as a literal.

                                    "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/","title":"ssp","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp","title":"trestle.oscal.ssp","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification","title":" AdjustmentJustification (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                    class AdjustmentJustification(OscalBaseModel):\n    __root__: str = Field(\n        ...,\n        description=\n        'If the selected security level is different from the base security level, this contains the justification for the change.',\n        title='Adjustment Justification'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__root__","title":"__root__: str pydantic-field required special","text":"

                                    If the selected security level is different from the base security level, this contains the justification for the change.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary","title":" AuthorizationBoundary (OscalBaseModel) pydantic-model","text":"

                                    A description of this system's authorization boundary, optionally supplemented by diagrams that illustrate the authorization boundary.

                                    Source code in trestle/oscal/ssp.py
                                    class AuthorizationBoundary(OscalBaseModel):\n\"\"\"\n    A description of this system's authorization boundary, optionally supplemented by diagrams that illustrate the authorization boundary.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(\n        ...,\n        description=\"A summary of the system's authorization boundary.\",\n        title='Authorization Boundary Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    diagrams: Optional[List[Diagram]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.description","title":"description: str pydantic-field required","text":"

                                    A summary of the system's authorization boundary.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.diagrams","title":"diagrams: List[trestle.oscal.ssp.Diagram] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base","title":" Base (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                    class Base(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description='The prescribed base (Confidentiality, Integrity, or Availability) security impact level.',\n        title='Base Level (Confidentiality, Integrity, or Availability)'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    The prescribed base (Confidentiality, Integrity, or Availability) security impact level.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent","title":" ByComponent (OscalBaseModel) pydantic-model","text":"

                                    Defines how the referenced component implements a set of controls.

                                    Source code in trestle/oscal/ssp.py
                                    class ByComponent(OscalBaseModel):\n\"\"\"\n    Defines how the referenced component implements a set of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description='A machine-oriented identifier reference to the component that is implemeting a given control.',\n        title='Component Universally Unique Identifier Reference'\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='By-Component Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes how a control or a control statement is implemented within the referenced system component.',\n        title='Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    implementation_status: Optional[common.ImplementationStatus] = Field(None, alias='implementation-status')\n    export: Optional[Export] = Field(\n        None,\n        description='Identifies content intended for external consumption, such as with leveraged organizations.',\n        title='Export'\n    )\n    inherited: Optional[List[Inherited]] = Field(None)\n    satisfied: Optional[List[Satisfied]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to the component that is implemeting a given control.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.description","title":"description: str pydantic-field required","text":"

                                    An implementation statement that describes how a control or a control statement is implemented within the referenced system component.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.export","title":"export: Export pydantic-field","text":"

                                    Identifies content intended for external consumption, such as with leveraged organizations.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.implementation_status","title":"implementation_status: ImplementationStatus pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.inherited","title":"inherited: List[trestle.oscal.ssp.Inherited] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.satisfied","title":"satisfied: List[trestle.oscal.ssp.Satisfied] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.set_parameters","title":"set_parameters: List[trestle.oscal.ssp.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization","title":" Categorization (OscalBaseModel) pydantic-model","text":"

                                    A set of information type identifiers qualified by the given identification system used, such as NIST SP 800-60.

                                    Source code in trestle/oscal/ssp.py
                                    class Categorization(OscalBaseModel):\n\"\"\"\n    A set of information type identifiers qualified by the given identification system used, such as NIST SP 800-60.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    system: Union[AnyUrl, System] = Field(\n        ...,\n        description='Specifies the information type identification system used.',\n        title='Information Type Identification System'\n    )\n    information_type_ids: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None, alias='information-type-ids')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.information_type_ids","title":"information_type_ids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.system","title":"system: Union[pydantic.v1.networks.AnyUrl, trestle.oscal.ssp.System] pydantic-field required","text":"

                                    Specifies the information type identification system used.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation","title":" ControlImplementation (OscalBaseModel) pydantic-model","text":"

                                    Describes how the system satisfies a set of controls.

                                    Source code in trestle/oscal/ssp.py
                                    class ControlImplementation(OscalBaseModel):\n\"\"\"\n    Describes how the system satisfies a set of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(\n        ...,\n        description=\n        'A statement describing important things to know about how this set of control satisfaction documentation is approached.',\n        title='Control Implementation Description'\n    )\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    implemented_requirements: List[ImplementedRequirement] = Field(..., alias='implemented-requirements')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.description","title":"description: str pydantic-field required","text":"

                                    A statement describing important things to know about how this set of control satisfaction documentation is approached.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.implemented_requirements","title":"implemented_requirements: List[trestle.oscal.ssp.ImplementedRequirement] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.set_parameters","title":"set_parameters: List[trestle.oscal.ssp.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow","title":" DataFlow (OscalBaseModel) pydantic-model","text":"

                                    A description of the logical flow of information within the system and across its boundaries, optionally supplemented by diagrams that illustrate these flows.

                                    Source code in trestle/oscal/ssp.py
                                    class DataFlow(OscalBaseModel):\n\"\"\"\n    A description of the logical flow of information within the system and across its boundaries, optionally supplemented by diagrams that illustrate these flows.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(..., description=\"A summary of the system's data flow.\", title='Data Flow Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    diagrams: Optional[List[Diagram]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.description","title":"description: str pydantic-field required","text":"

                                    A summary of the system's data flow.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.diagrams","title":"diagrams: List[trestle.oscal.ssp.Diagram] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized","title":" DateAuthorized (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                    class DateAuthorized(OscalBaseModel):\n    __root__: DateDatatype = Field(\n        ..., description='The date the system received its authorization.', title='System Authorization Date'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__root__","title":"__root__: DateDatatype pydantic-field required special","text":"

                                    The date the system received its authorization.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype","title":" DateDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                    class DateDatatype(OscalBaseModel):\n    __root__: constr(\n        regex=\n        r'^(((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))(Z|(-((0[0-9]|1[0-2]):00|0[39]:30)|\\+((0[0-9]|1[0-4]):00|(0[34569]|10):30|(0[58]|12):45)))?$'\n    ) = Field(..., description='A string representing a 24-hour period with an optional timezone.')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    A string representing a 24-hour period with an optional timezone.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram","title":" Diagram (OscalBaseModel) pydantic-model","text":"

                                    A graphic that provides a visual representation the system, or some aspect of it.

                                    Source code in trestle/oscal/ssp.py
                                    class Diagram(OscalBaseModel):\n\"\"\"\n    A graphic that provides a visual representation the system, or some aspect of it.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this diagram elsewhere in this or other OSCAL instances. The locally defined UUID of the diagram can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Diagram ID'\n    )\n    description: Optional[str] = Field(None, description='A summary of the diagram.', title='Diagram Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    caption: Optional[str] = Field(None, description='A brief caption to annotate the diagram.', title='Caption')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.caption","title":"caption: str pydantic-field","text":"

                                    A brief caption to annotate the diagram.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.description","title":"description: str pydantic-field","text":"

                                    A summary of the diagram.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this diagram elsewhere in this or other OSCAL instances. The locally defined UUID of the diagram can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export","title":" Export (OscalBaseModel) pydantic-model","text":"

                                    Identifies content intended for external consumption, such as with leveraged organizations.

                                    Source code in trestle/oscal/ssp.py
                                    class Export(OscalBaseModel):\n\"\"\"\n    Identifies content intended for external consumption, such as with leveraged organizations.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None,\n        description=\n        'An implementation statement that describes the aspects of the control or control statement implementation that can be available to another system leveraging this system.',\n        title='Control Implementation Export Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    provided: Optional[List[Provided]] = Field(None)\n    responsibilities: Optional[List[Responsibility]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.description","title":"description: str pydantic-field","text":"

                                    An implementation statement that describes the aspects of the control or control statement implementation that can be available to another system leveraging this system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.provided","title":"provided: List[trestle.oscal.ssp.Provided] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.responsibilities","title":"responsibilities: List[trestle.oscal.ssp.Responsibility] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact","title":" Impact (OscalBaseModel) pydantic-model","text":"

                                    The expected level of impact resulting from the described information.

                                    Source code in trestle/oscal/ssp.py
                                    class Impact(OscalBaseModel):\n\"\"\"\n    The expected level of impact resulting from the described information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    base: Base\n    selected: Optional[Selected] = None\n    adjustment_justification: Optional[AdjustmentJustification] = Field(None, alias='adjustment-justification')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.adjustment_justification","title":"adjustment_justification: AdjustmentJustification pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.base","title":"base: Base pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.selected","title":"selected: Selected pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement","title":" ImplementedRequirement (OscalBaseModel) pydantic-model","text":"

                                    Describes how the system satisfies the requirements of an individual control.

                                    Source code in trestle/oscal/ssp.py
                                    class ImplementedRequirement(OscalBaseModel):\n\"\"\"\n    Describes how the system satisfies the requirements of an individual control.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control requirement elsewhere in this or other OSCAL instances. The locally defined UUID of the control requirement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Control Requirement Universally Unique Identifier',\n    )\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    statements: Optional[List[Statement]] = Field(None)\n    by_components: Optional[List[ByComponent]] = Field(None, alias='by-components')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.by_components","title":"by_components: List[trestle.oscal.ssp.ByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                    A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.set_parameters","title":"set_parameters: List[trestle.oscal.ssp.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.statements","title":"statements: List[trestle.oscal.ssp.Statement] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control requirement elsewhere in this or other OSCAL instances. The locally defined UUID of the control requirement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile","title":" ImportProfile (OscalBaseModel) pydantic-model","text":"

                                    Used to import the OSCAL profile representing the system's control baseline.

                                    Source code in trestle/oscal/ssp.py
                                    class ImportProfile(OscalBaseModel):\n\"\"\"\n    Used to import the OSCAL profile representing the system's control baseline.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description=\"A resolvable URL reference to the profile or catalog to use as the system's control baseline.\",\n        title='Profile Reference'\n    )\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.href","title":"href: str pydantic-field required","text":"

                                    A resolvable URL reference to the profile or catalog to use as the system's control baseline.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType","title":" InformationType (OscalBaseModel) pydantic-model","text":"

                                    Contains details about one information type that is stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.

                                    Source code in trestle/oscal/ssp.py
                                    class InformationType(OscalBaseModel):\n\"\"\"\n    Contains details about one information type that is stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this information type elsewhere in this or other OSCAL instances. The locally defined UUID of the information type can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Information Type Universally Unique Identifier',\n    )\n    title: str = Field(\n        ...,\n        description=\n        'A human readable name for the information type. This title should be meaningful within the context of the system.',\n        title='title field'\n    )\n    description: str = Field(\n        ...,\n        description='A summary of how this information type is used within the system.',\n        title='Information Type Description'\n    )\n    categorizations: Optional[List[Categorization]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    confidentiality_impact: Optional[Impact] = Field(None, alias='confidentiality-impact')\n    integrity_impact: Optional[Impact] = Field(None, alias='integrity-impact')\n    availability_impact: Optional[Impact] = Field(None, alias='availability-impact')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.availability_impact","title":"availability_impact: Impact pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.categorizations","title":"categorizations: List[trestle.oscal.ssp.Categorization] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.confidentiality_impact","title":"confidentiality_impact: Impact pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.description","title":"description: str pydantic-field required","text":"

                                    A summary of how this information type is used within the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.integrity_impact","title":"integrity_impact: Impact pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.title","title":"title: str pydantic-field required","text":"

                                    A human readable name for the information type. This title should be meaningful within the context of the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this information type elsewhere in this or other OSCAL instances. The locally defined UUID of the information type can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited","title":" Inherited (OscalBaseModel) pydantic-model","text":"

                                    Describes a control implementation inherited by a leveraging system.

                                    Source code in trestle/oscal/ssp.py
                                    class Inherited(OscalBaseModel):\n\"\"\"\n    Describes a control implementation inherited by a leveraging system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inherited entry elsewhere in this or other OSCAL instances. The locally defined UUID of the inherited control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Inherited Universally Unique Identifier',\n    )\n    provided_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='provided-uuid',\n        description=\n        'A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.',\n        title='Provided UUID'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is inheriting from a leveraged system.',\n        title='Inherited Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.description","title":"description: str pydantic-field required","text":"

                                    An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is inheriting from a leveraged system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.provided_uuid","title":"provided_uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inherited entry elsewhere in this or other OSCAL instances. The locally defined UUID of the inherited control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization","title":" LeveragedAuthorization (OscalBaseModel) pydantic-model","text":"

                                    A description of another authorized system from which this system inherits capabilities that satisfy security requirements. Another term for this concept is a common control provider.

                                    Source code in trestle/oscal/ssp.py
                                    class LeveragedAuthorization(OscalBaseModel):\n\"\"\"\n    A description of another authorized system from which this system inherits capabilities that satisfy security requirements. Another term for this concept is a common control provider.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope and can be used to reference this leveraged authorization elsewhere in this or other OSCAL instances. The locally defined UUID of the leveraged authorization can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Leveraged Authorization Universally Unique Identifier',\n    )\n    title: str = Field(\n        ...,\n        description='A human readable name for the leveraged authorization in the context of the system.',\n        title='title field'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    party_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='party-uuid',\n        description='A machine-oriented identifier reference to the party that manages the leveraged system.',\n        title='party-uuid field'\n    )\n    date_authorized: DateAuthorized = Field(..., alias='date-authorized')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.date_authorized","title":"date_authorized: DateAuthorized pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.party_uuid","title":"party_uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented identifier reference to the party that manages the leveraged system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.title","title":"title: str pydantic-field required","text":"

                                    A human readable name for the leveraged authorization in the context of the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope and can be used to reference this leveraged authorization elsewhere in this or other OSCAL instances. The locally defined UUID of the leveraged authorization can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                    class Model(OscalBaseModel):\n    system_security_plan: SystemSecurityPlan = Field(..., alias='system-security-plan')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.system_security_plan","title":"system_security_plan: SystemSecurityPlan pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture","title":" NetworkArchitecture (OscalBaseModel) pydantic-model","text":"

                                    A description of the system's network architecture, optionally supplemented by diagrams that illustrate the network architecture.

                                    Source code in trestle/oscal/ssp.py
                                    class NetworkArchitecture(OscalBaseModel):\n\"\"\"\n    A description of the system's network architecture, optionally supplemented by diagrams that illustrate the network architecture.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(\n        ..., description=\"A summary of the system's network architecture.\", title='Network Architecture Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    diagrams: Optional[List[Diagram]] = Field(None)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.description","title":"description: str pydantic-field required","text":"

                                    A summary of the system's network architecture.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.diagrams","title":"diagrams: List[trestle.oscal.ssp.Diagram] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues","title":" OperationalStateValidValues (Enum) ","text":"Source code in trestle/oscal/ssp.py
                                    class OperationalStateValidValues(Enum):\n    operational = 'operational'\n    under_development = 'under-development'\n    under_major_modification = 'under-major-modification'\n    disposition = 'disposition'\n    other = 'other'\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.disposition","title":"disposition","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.operational","title":"operational","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.other","title":"other","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.under_development","title":"under_development","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.under_major_modification","title":"under_major_modification","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided","title":" Provided (OscalBaseModel) pydantic-model","text":"

                                    Describes a capability which may be inherited by a leveraging system.

                                    Source code in trestle/oscal/ssp.py
                                    class Provided(OscalBaseModel):\n\"\"\"\n    Describes a capability which may be inherited by a leveraging system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this provided entry elsewhere in this or other OSCAL instances. The locally defined UUID of the provided entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Provided Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of the control or control statement implementation that can be provided to another system leveraging this system.',\n        title='Provided Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.description","title":"description: str pydantic-field required","text":"

                                    An implementation statement that describes the aspects of the control or control statement implementation that can be provided to another system leveraging this system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this provided entry elsewhere in this or other OSCAL instances. The locally defined UUID of the provided entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility","title":" Responsibility (OscalBaseModel) pydantic-model","text":"

                                    Describes a control implementation responsibility imposed on a leveraging system.

                                    Source code in trestle/oscal/ssp.py
                                    class Responsibility(OscalBaseModel):\n\"\"\"\n    Describes a control implementation responsibility imposed on a leveraging system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this responsibility elsewhere in this or other OSCAL instances. The locally defined UUID of the responsibility can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Responsibility Universally Unique Identifier',\n    )\n    provided_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='provided-uuid',\n        description=\n        'A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.',\n        title='Provided UUID'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of the control or control statement implementation that a leveraging system must implement to satisfy the control provided by a leveraged system.',\n        title='Control Implementation Responsibility Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.description","title":"description: str pydantic-field required","text":"

                                    An implementation statement that describes the aspects of the control or control statement implementation that a leveraging system must implement to satisfy the control provided by a leveraged system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.provided_uuid","title":"provided_uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this responsibility elsewhere in this or other OSCAL instances. The locally defined UUID of the responsibility can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied","title":" Satisfied (OscalBaseModel) pydantic-model","text":"

                                    Describes how this system satisfies a responsibility imposed by a leveraged system.

                                    Source code in trestle/oscal/ssp.py
                                    class Satisfied(OscalBaseModel):\n\"\"\"\n    Describes how this system satisfies a responsibility imposed by a leveraged system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this satisfied control implementation entry elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Satisfied Universally Unique Identifier',\n    )\n    responsibility_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='responsibility-uuid',\n        description=\n        'A machine-oriented identifier reference to a control implementation that satisfies a responsibility imposed by a leveraged system.',\n        title='Responsibility UUID'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is implementing based on a requirement from a leveraged system.',\n        title='Satisfied Control Implementation Responsibility Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.description","title":"description: str pydantic-field required","text":"

                                    An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is implementing based on a requirement from a leveraged system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.responsibility_uuid","title":"responsibility_uuid: ConstrainedStrValue pydantic-field","text":"

                                    A machine-oriented identifier reference to a control implementation that satisfies a responsibility imposed by a leveraged system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this satisfied control implementation entry elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel","title":" SecurityImpactLevel (OscalBaseModel) pydantic-model","text":"

                                    The overall level of expected impact resulting from unauthorized disclosure, modification, or loss of access to information.

                                    Source code in trestle/oscal/ssp.py
                                    class SecurityImpactLevel(OscalBaseModel):\n\"\"\"\n    The overall level of expected impact resulting from unauthorized disclosure, modification, or loss of access to information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    security_objective_confidentiality: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        alias='security-objective-confidentiality',\n        description=\n        'A target-level of confidentiality for the system, based on the sensitivity of information within the system.',\n        title='Security Objective: Confidentiality'\n    )\n    security_objective_integrity: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        alias='security-objective-integrity',\n        description=\n        'A target-level of integrity for the system, based on the sensitivity of information within the system.',\n        title='Security Objective: Integrity'\n    )\n    security_objective_availability: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        alias='security-objective-availability',\n        description=\n        'A target-level of availability for the system, based on the sensitivity of information within the system.',\n        title='Security Objective: Availability'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.security_objective_availability","title":"security_objective_availability: ConstrainedStrValue pydantic-field required","text":"

                                    A target-level of availability for the system, based on the sensitivity of information within the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.security_objective_confidentiality","title":"security_objective_confidentiality: ConstrainedStrValue pydantic-field required","text":"

                                    A target-level of confidentiality for the system, based on the sensitivity of information within the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.security_objective_integrity","title":"security_objective_integrity: ConstrainedStrValue pydantic-field required","text":"

                                    A target-level of integrity for the system, based on the sensitivity of information within the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected","title":" Selected (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                    class Selected(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description='The selected (Confidentiality, Integrity, or Availability) security impact level.',\n        title='Selected Level (Confidentiality, Integrity, or Availability)'\n    )\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                    The selected (Confidentiality, Integrity, or Availability) security impact level.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter","title":" SetParameter (OscalBaseModel) pydantic-model","text":"

                                    Identifies the parameter that will be set by the enclosed value.

                                    Source code in trestle/oscal/ssp.py
                                    class SetParameter(OscalBaseModel):\n\"\"\"\n    Identifies the parameter that will be set by the enclosed value.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    param_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='param-id',\n        description=\n        \"A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.\",\n        title='Parameter ID'\n    )\n    values: List[constr(regex=r'^\\S(.*\\S)?$')] = Field(...)\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement","title":" Statement (OscalBaseModel) pydantic-model","text":"

                                    Identifies which statements within a control are addressed.

                                    Source code in trestle/oscal/ssp.py
                                    class Statement(OscalBaseModel):\n\"\"\"\n    Identifies which statements within a control are addressed.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    statement_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='statement-id',\n        description='A human-oriented identifier reference to a control statement.',\n        title='Control Statement Reference'\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).',\n        title='Control Statement Reference Universally Unique Identifier'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    by_components: Optional[List[ByComponent]] = Field(None, alias='by-components')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.by_components","title":"by_components: List[trestle.oscal.ssp.ByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.statement_id","title":"statement_id: ConstrainedStrValue pydantic-field required","text":"

                                    A human-oriented identifier reference to a control statement.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1","title":" Status1 (OscalBaseModel) pydantic-model","text":"

                                    Describes the operational status of the system.

                                    Source code in trestle/oscal/ssp.py
                                    class Status1(OscalBaseModel):\n\"\"\"\n    Describes the operational status of the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: OperationalStateValidValues = Field(..., description='The current operating status.', title='State')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.state","title":"state: OperationalStateValidValues pydantic-field required","text":"

                                    The current operating status.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.System","title":" System (Enum) ","text":"

                                    Specifies the information type identification system used.

                                    Source code in trestle/oscal/ssp.py
                                    class System(Enum):\n\"\"\"\n    Specifies the information type identification system used.\n    \"\"\"\n\n    http___doi_org_10_6028_NIST_SP_800_60v2r1 = 'http://doi.org/10.6028/NIST.SP.800-60v2r1'\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.System.http___doi_org_10_6028_NIST_SP_800_60v2r1","title":"http___doi_org_10_6028_NIST_SP_800_60v2r1","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics","title":" SystemCharacteristics (OscalBaseModel) pydantic-model","text":"

                                    Contains the characteristics of the system, such as its name, purpose, and security impact level.

                                    Source code in trestle/oscal/ssp.py
                                    class SystemCharacteristics(OscalBaseModel):\n\"\"\"\n    Contains the characteristics of the system, such as its name, purpose, and security impact level.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    system_ids: List[common.SystemId] = Field(..., alias='system-ids')\n    system_name: constr(\n        regex=r'^\\S(.*\\S)?$'\n    ) = Field(..., alias='system-name', description='The full name of the system.', title='System Name - Full')\n    system_name_short: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='system-name-short',\n        description=\n        'A short name for the system, such as an acronym, that is suitable for display in a data table or summary list.',\n        title='System Name - Short'\n    )\n    description: str = Field(..., description='A summary of the system.', title='System Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    date_authorized: Optional[DateAuthorized] = Field(None, alias='date-authorized')\n    security_sensitivity_level: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='security-sensitivity-level',\n        description='The overall information system sensitivity categorization, such as defined by FIPS-199.',\n        title='Security Sensitivity Level'\n    )\n    system_information: SystemInformation = Field(..., alias='system-information')\n    security_impact_level: Optional[SecurityImpactLevel] = Field(None, alias='security-impact-level')\n    status: Status1\n    authorization_boundary: AuthorizationBoundary = Field(..., alias='authorization-boundary')\n    network_architecture: Optional[NetworkArchitecture] = Field(None, alias='network-architecture')\n    data_flow: Optional[DataFlow] = Field(None, alias='data-flow')\n    responsible_parties: Optional[List[common.ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.authorization_boundary","title":"authorization_boundary: AuthorizationBoundary pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.data_flow","title":"data_flow: DataFlow pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.date_authorized","title":"date_authorized: DateAuthorized pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.description","title":"description: str pydantic-field required","text":"

                                    A summary of the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.network_architecture","title":"network_architecture: NetworkArchitecture pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.security_impact_level","title":"security_impact_level: SecurityImpactLevel pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.security_sensitivity_level","title":"security_sensitivity_level: ConstrainedStrValue pydantic-field","text":"

                                    The overall information system sensitivity categorization, such as defined by FIPS-199.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.status","title":"status: Status1 pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_ids","title":"system_ids: List[trestle.oscal.common.SystemId] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_information","title":"system_information: SystemInformation pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_name","title":"system_name: ConstrainedStrValue pydantic-field required","text":"

                                    The full name of the system.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_name_short","title":"system_name_short: ConstrainedStrValue pydantic-field","text":"

                                    A short name for the system, such as an acronym, that is suitable for display in a data table or summary list.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation","title":" SystemImplementation (OscalBaseModel) pydantic-model","text":"

                                    Provides information as to how the system is implemented.

                                    Source code in trestle/oscal/ssp.py
                                    class SystemImplementation(OscalBaseModel):\n\"\"\"\n    Provides information as to how the system is implemented.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    leveraged_authorizations: Optional[List[LeveragedAuthorization]] = Field(None, alias='leveraged-authorizations')\n    users: List[common.SystemUser] = Field(...)\n    components: List[common.SystemComponent] = Field(...)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    remarks: Optional[str] = None\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.leveraged_authorizations","title":"leveraged_authorizations: List[trestle.oscal.ssp.LeveragedAuthorization] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.users","title":"users: List[trestle.oscal.common.SystemUser] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation","title":" SystemInformation (OscalBaseModel) pydantic-model","text":"

                                    Contains details about all information types that are stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.

                                    Source code in trestle/oscal/ssp.py
                                    class SystemInformation(OscalBaseModel):\n\"\"\"\n    Contains details about all information types that are stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    information_types: List[InformationType] = Field(..., alias='information-types')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.information_types","title":"information_types: List[trestle.oscal.ssp.InformationType] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan","title":" SystemSecurityPlan (OscalBaseModel) pydantic-model","text":"

                                    A system security plan, such as those described in NIST SP 800-18.

                                    Source code in trestle/oscal/ssp.py
                                    class SystemSecurityPlan(OscalBaseModel):\n\"\"\"\n    A system security plan, such as those described in NIST SP 800-18.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this system security plan (SSP) elsewhere in this or other OSCAL instances. The locally defined UUID of the SSP can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='System Security Plan Universally Unique Identifier',\n    )\n    metadata: common.Metadata\n    import_profile: ImportProfile = Field(..., alias='import-profile')\n    system_characteristics: SystemCharacteristics = Field(..., alias='system-characteristics')\n    system_implementation: SystemImplementation = Field(..., alias='system-implementation')\n    control_implementation: ControlImplementation = Field(..., alias='control-implementation')\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.control_implementation","title":"control_implementation: ControlImplementation pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.import_profile","title":"import_profile: ImportProfile pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.system_characteristics","title":"system_characteristics: SystemCharacteristics pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.system_implementation","title":"system_implementation: SystemImplementation pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                    A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this system security plan (SSP) elsewhere in this or other OSCAL instances. The locally defined UUID of the SSP can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                    "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                    class Config:\n    extra = Extra.forbid\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/","title":"base_task","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task","title":"trestle.tasks.base_task","text":"

                                    Trestle tasks base templating.

                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail","title":" PassFail (TaskBase) ","text":"

                                    Holding pattern template for a task which does nothing and always passes.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/base_task.py
                                    class PassFail(TaskBase):\n\"\"\"\n    Holding pattern template for a task which does nothing and always passes.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'pass-fail'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task pass-fail.\n\n        Attributes:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('This is a template task which reports pass fail depending on the specific configuration.')\n        logger.info(\n            'In this case if no config section is provided the task will fail. This a a task specific behavior.'\n        )\n        logger.info('Configuration flags sit under [task.pass-fail]')\n        logger.info('with two boolean flags')\n        logger.info('execute_status = True/False with a default pass')\n        logger.info('simulate_status = True/False with a default fail')\n        logger.info('Note that if the config file does not have the appropriate section this should fail.')\n        logger.info('The princple goal is a simple development example.')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        if self._config:\n            outcome = self._config.getboolean('simulate_status', fallback=True)\n            if outcome:\n                return TaskOutcome('simulated-success')\n        return TaskOutcome('simulated-failure')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide a actual outcome.\"\"\"\n        if self._config:\n            outcome = self._config.getboolean('execute_status', fallback=True)\n            if outcome:\n                return TaskOutcome('success')\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task pass-fail.

                                    Attributes:

                                    Name Type Description config_object

                                    Config section associated with the task.

                                    Source code in trestle/tasks/base_task.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task pass-fail.\n\n    Attributes:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.execute","title":"execute(self)","text":"

                                    Provide a actual outcome.

                                    Source code in trestle/tasks/base_task.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide a actual outcome.\"\"\"\n    if self._config:\n        outcome = self._config.getboolean('execute_status', fallback=True)\n        if outcome:\n            return TaskOutcome('success')\n    return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/base_task.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('This is a template task which reports pass fail depending on the specific configuration.')\n    logger.info(\n        'In this case if no config section is provided the task will fail. This a a task specific behavior.'\n    )\n    logger.info('Configuration flags sit under [task.pass-fail]')\n    logger.info('with two boolean flags')\n    logger.info('execute_status = True/False with a default pass')\n    logger.info('simulate_status = True/False with a default fail')\n    logger.info('Note that if the config file does not have the appropriate section this should fail.')\n    logger.info('The princple goal is a simple development example.')\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/base_task.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    if self._config:\n        outcome = self._config.getboolean('simulate_status', fallback=True)\n        if outcome:\n            return TaskOutcome('simulated-success')\n    return TaskOutcome('simulated-failure')\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase","title":" TaskBase (ABC) ","text":"

                                    Abstract base class for tasks.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/base_task.py
                                    class TaskBase(ABC):\n\"\"\"\n    Abstract base class for tasks.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name: str = 'base'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"Initialize task base and store config.\"\"\"\n        self._config = config_object\n\n    @abstractmethod\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n\n    @abstractmethod\n    def execute(self) -> TaskOutcome:\n\"\"\"Execute the task including potential rollback.\"\"\"\n\n    @abstractmethod\n    def simulate(self) -> TaskOutcome:\n\"\"\"Simulate the task and report task outcome.\"\"\"\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize task base and store config.

                                    Source code in trestle/tasks/base_task.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"Initialize task base and store config.\"\"\"\n    self._config = config_object\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.execute","title":"execute(self)","text":"

                                    Execute the task including potential rollback.

                                    Source code in trestle/tasks/base_task.py
                                    @abstractmethod\ndef execute(self) -> TaskOutcome:\n\"\"\"Execute the task including potential rollback.\"\"\"\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/base_task.py
                                    @abstractmethod\ndef print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.simulate","title":"simulate(self)","text":"

                                    Simulate the task and report task outcome.

                                    Source code in trestle/tasks/base_task.py
                                    @abstractmethod\ndef simulate(self) -> TaskOutcome:\n\"\"\"Simulate the task and report task outcome.\"\"\"\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome","title":" TaskOutcome (Enum) ","text":"

                                    Enum describing possible task outcomes.

                                    Source code in trestle/tasks/base_task.py
                                    class TaskOutcome(Enum):\n\"\"\"Enum describing possible task outcomes.\"\"\"\n\n    SUCCESS = 'success'\n    FAILURE = 'failure'\n    ROLLEDBACK = 'rolledback'\n    SIM_SUCCESS = 'simulated-success'\n    SIM_FAILURE = 'simulated-failure'\n    NOT_IMPLEMENTED = 'not-implemented'\n
                                    "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.FAILURE","title":"FAILURE","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.NOT_IMPLEMENTED","title":"NOT_IMPLEMENTED","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.ROLLEDBACK","title":"ROLLEDBACK","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.SIM_FAILURE","title":"SIM_FAILURE","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.SIM_SUCCESS","title":"SIM_SUCCESS","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.SUCCESS","title":"SUCCESS","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/","title":"cis_xlsx_to_oscal_catalog","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog","title":"trestle.tasks.cis_xlsx_to_oscal_catalog","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.timestamp","title":"timestamp","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper","title":" CatalogHelper ","text":"

                                    OSCAL Catalog Helper.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    class CatalogHelper:\n\"\"\"OSCAL Catalog Helper.\"\"\"\n\n    def __init__(self, title: str, version: str) -> None:\n\"\"\"Initialize.\"\"\"\n        # metadata\n        self._metadata = Metadata(title=title, last_modified=timestamp, oscal_version=OSCAL_VERSION, version=version)\n        self._root_group = OrderedDict()\n        self._root_resources = OrderedDict()\n        self._all_groups = OrderedDict()\n        self._all_controls = OrderedDict()\n\n    def add_group(self, section: str, title: str, props: List[Property], parts: List[Part]) -> None:\n\"\"\"Add group.\"\"\"\n        numdots = section.count('.')\n        if numdots == 0:\n            group = Group(title=f'{title}', id=f'CIS-{section}')\n            if props:\n                group.props = props\n            if parts:\n                group.parts = parts\n            self._root_group[section] = group\n            self._all_groups[section] = group\n        else:\n            key = '.'.join(section.split('.')[:-1])\n            parent = self._all_groups[key]\n            if parent.groups is None:\n                parent.groups = []\n            group = Group(title=f'{title}', id=f'CIS-{section}')\n            if props:\n                group.props = props\n            if parts:\n                group.parts = parts\n            parent.groups.append(group)\n            self._all_groups[section] = group\n\n    def _add_prop(self, control: Control, prop: Property) -> None:\n\"\"\"Add property to control.\"\"\"\n        control_props = control.props\n        control.props = []\n        last = 0\n        for i, control_prop in enumerate(control_props):\n            if control_prop.name == prop.name:\n                last = i\n        for i, control_prop in enumerate(control_props):\n            control.props.append(control_prop)\n            if i == last:\n                control.props.append(prop)\n\n    def add_control(\n        self,\n        section: str,\n        recommendation: str,\n        title: str,\n        props: List[Property],\n        parts: List[Part],\n        links: List[Link]\n    ) -> None:\n\"\"\"Add control.\"\"\"\n        group = self._all_groups[section]\n        if group.controls is None:\n            group.controls = []\n        id_ = f'CIS-{recommendation}'\n        if id_ in self._all_controls:\n            control = self._all_controls[id_]\n            for prop in props:\n                if prop.name == 'profile':\n                    self._add_prop(control, prop)\n        else:\n            title = f'{title}'\n            control = Control(id=id_, title=title)\n            self._all_controls[id_] = control\n            if props:\n                control.props = props\n            if parts:\n                control.parts = parts\n            if links:\n                control.links = links\n            group.controls.append(control)\n\n    def add_link(\n        self,\n        recommendation: str,\n        reference: str,\n        links: List[Link],\n    ) -> None:\n\"\"\"Add link.\"\"\"\n        id_ = f'CIS-{recommendation}'\n        if id_ not in self._root_resources:\n            res_id = str(uuid.uuid4())\n            link = Link(href=f'#{res_id}', rel='reference')\n            links.append(link)\n            resource = Resource(\n                uuid=res_id,\n                description=reference,\n            )\n            self._root_resources[id_] = resource\n\n    def get_catalog(self) -> Catalog:\n\"\"\"Get catalog.\"\"\"\n        back_matter = BackMatter(resources=list(self._root_resources.values()))\n        catalog = Catalog(\n            uuid=str(uuid.uuid4()),\n            metadata=self._metadata,\n            groups=list(self._root_group.values()),\n            back_matter=back_matter\n        )\n        return catalog\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.__init__","title":"__init__(self, title, version) special","text":"

                                    Initialize.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def __init__(self, title: str, version: str) -> None:\n\"\"\"Initialize.\"\"\"\n    # metadata\n    self._metadata = Metadata(title=title, last_modified=timestamp, oscal_version=OSCAL_VERSION, version=version)\n    self._root_group = OrderedDict()\n    self._root_resources = OrderedDict()\n    self._all_groups = OrderedDict()\n    self._all_controls = OrderedDict()\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.add_control","title":"add_control(self, section, recommendation, title, props, parts, links)","text":"

                                    Add control.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def add_control(\n    self,\n    section: str,\n    recommendation: str,\n    title: str,\n    props: List[Property],\n    parts: List[Part],\n    links: List[Link]\n) -> None:\n\"\"\"Add control.\"\"\"\n    group = self._all_groups[section]\n    if group.controls is None:\n        group.controls = []\n    id_ = f'CIS-{recommendation}'\n    if id_ in self._all_controls:\n        control = self._all_controls[id_]\n        for prop in props:\n            if prop.name == 'profile':\n                self._add_prop(control, prop)\n    else:\n        title = f'{title}'\n        control = Control(id=id_, title=title)\n        self._all_controls[id_] = control\n        if props:\n            control.props = props\n        if parts:\n            control.parts = parts\n        if links:\n            control.links = links\n        group.controls.append(control)\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.add_group","title":"add_group(self, section, title, props, parts)","text":"

                                    Add group.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def add_group(self, section: str, title: str, props: List[Property], parts: List[Part]) -> None:\n\"\"\"Add group.\"\"\"\n    numdots = section.count('.')\n    if numdots == 0:\n        group = Group(title=f'{title}', id=f'CIS-{section}')\n        if props:\n            group.props = props\n        if parts:\n            group.parts = parts\n        self._root_group[section] = group\n        self._all_groups[section] = group\n    else:\n        key = '.'.join(section.split('.')[:-1])\n        parent = self._all_groups[key]\n        if parent.groups is None:\n            parent.groups = []\n        group = Group(title=f'{title}', id=f'CIS-{section}')\n        if props:\n            group.props = props\n        if parts:\n            group.parts = parts\n        parent.groups.append(group)\n        self._all_groups[section] = group\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.add_link","title":"add_link(self, recommendation, reference, links)","text":"

                                    Add link.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def add_link(\n    self,\n    recommendation: str,\n    reference: str,\n    links: List[Link],\n) -> None:\n\"\"\"Add link.\"\"\"\n    id_ = f'CIS-{recommendation}'\n    if id_ not in self._root_resources:\n        res_id = str(uuid.uuid4())\n        link = Link(href=f'#{res_id}', rel='reference')\n        links.append(link)\n        resource = Resource(\n            uuid=res_id,\n            description=reference,\n        )\n        self._root_resources[id_] = resource\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.get_catalog","title":"get_catalog(self)","text":"

                                    Get catalog.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def get_catalog(self) -> Catalog:\n\"\"\"Get catalog.\"\"\"\n    back_matter = BackMatter(resources=list(self._root_resources.values()))\n    catalog = Catalog(\n        uuid=str(uuid.uuid4()),\n        metadata=self._metadata,\n        groups=list(self._root_group.values()),\n        back_matter=back_matter\n    )\n    return catalog\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog","title":" CisXlsxToOscalCatalog (TaskBase) ","text":"

                                    Task to transform CIS .xlsx to OSCAL catalog.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    class CisXlsxToOscalCatalog(TaskBase):\n\"\"\"\n    Task to transform CIS .xlsx to OSCAL catalog.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'cis-xlsx-to-oscal-catalog'\n    ns = 'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/catalog/cis'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.cis-xlsx-to-oscal-catalog]:')\n        text1 = '  input-file             = '\n        text2 = '(required) path to read the compliance-as-code .xlsx spread sheet file.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = '(required) location to write the generated catalog.json file.'\n        logger.info(text1 + text2)\n        text1 = '  title                  = '\n        text2 = '(required) title of the CIS catalog.'\n        logger.info(text1 + text2)\n        text1 = '  version                = '\n        text2 = '(required) version of the CIS catalog.'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite       = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _get_normalized_name(self, key: str) -> str:\n\"\"\"Get normalized name.\"\"\"\n        name = key\n        name = name.replace(' ', '_')\n        name = name.replace('&', 'a')\n        name = name.replace('(', '')\n        name = name.replace(')', '')\n        return name\n\n    def _create_property(self, name: str, value: str) -> Property:\n        return Property(name=name, value=value, ns=CisXlsxToOscalCatalog.ns)\n\n    def _add_property(self, xlsx_helper: XlsxHelper, props: List[Property], row: int, key: str) -> None:\n\"\"\"Add property.\"\"\"\n        name = self._get_normalized_name(key)\n        value = xlsx_helper.get(row, key)\n        if value:\n            props.append(self._create_property(name, value))\n\n    def _add_property_boolean(self, xlsx_helper: XlsxHelper, props: List[Property], row: int, key: str) -> None:\n\"\"\"Add property.\"\"\"\n        name = self._get_normalized_name(key)\n        value = xlsx_helper.get(row, key)\n        if value:\n            props.append(self._create_property(name, 'True'))\n        else:\n            props.append(self._create_property(name, 'False'))\n\n    def _add_part(self, xlsx_helper: XlsxHelper, parts: List[Part], id_: str, row: int, key: str) -> None:\n\"\"\"Add part.\"\"\"\n        value = xlsx_helper.get(row, key)\n        if value:\n            name = self._get_normalized_name(key)\n            parts.append(Part(id=id_, name=name, prose=value))\n\n    def _add_links(\n        self, xlsx_helper: XlsxHelper, catalog_helper: CatalogHelper, links: List[Link], row: int, key: str\n    ) -> None:\n\"\"\"Add links.\"\"\"\n        value = xlsx_helper.get(row, key)\n        if value:\n            recommendation = xlsx_helper.get(row, 'recommendation #')\n            catalog_helper.add_link(recommendation, value, links)\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Wrap the execute for exception handling.\"\"\"\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        try:\n            ifile = self._config['input-file']\n            odir = self._config['output-dir']\n            title = self._config['title']\n            version = self._config['version']\n        except KeyError as e:\n            logger.info(f'key {e.args[0]} missing')\n            return TaskOutcome('failure')\n        # verbosity\n        _quiet = self._config.get('quiet', False)\n        _verbose = not _quiet\n        # output\n        overwrite = self._config.getboolean('output-overwrite', True)\n        opth = pathlib.Path(odir)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'catalog.json'\n        ofile = opth / oname\n        if not overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        xlsx_helper = XlsxHelper(ifile)\n        catalog_helper = CatalogHelper(title, version)\n        if xlsx_helper.is_ocp():\n            self._process_ocp(xlsx_helper, catalog_helper)\n        else:\n            self._process_rhel(xlsx_helper, catalog_helper)\n        catalog = catalog_helper.get_catalog()\n        # write OSCAL ComponentDefinition to file\n        if _verbose:\n            logger.info(f'output: {ofile}')\n        catalog.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _process_ocp(self, xlsx_helper: XlsxHelper, catalog_helper: CatalogHelper) -> None:\n\"\"\"Process OCP.\"\"\"\n        # transform each row into OSCAL equivalent\n        for row in xlsx_helper.row_generator():\n            section = xlsx_helper.get(row, 'section #')\n            recommendation = xlsx_helper.get(row, 'recommendation #')\n            title = xlsx_helper.get(row, 'title')\n            # init\n            props = []\n            parts = []\n            links = []\n            # props\n            self._add_property(xlsx_helper, props, row, 'profile')\n            self._add_property(xlsx_helper, props, row, 'status')\n            self._add_property(xlsx_helper, props, row, 'assessment status')\n            if recommendation is None:\n                frag = section\n            else:\n                frag = recommendation\n            # parts\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_smt', row, 'statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rat', row, 'rationale statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_imp', row, 'impact statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rem', row, 'remediation procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_aud', row, 'audit procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_inf', row, 'additional information')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_ctl', row, 'CIS Controls')\n            # group or control\n            if recommendation is None:\n                catalog_helper.add_group(section, title, props, parts)\n            else:\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG3')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG3')\n                self._add_property(xlsx_helper, props, row, 'MITRE ATT&CK Mappings')\n                self._add_links(xlsx_helper, catalog_helper, links, row, 'references')\n                catalog_helper.add_control(section, recommendation, title, props, parts, links)\n\n    def _process_rhel(self, xlsx_helper: XlsxHelper, catalog_helper: CatalogHelper) -> None:\n\"\"\"Process RHEL.\"\"\"\n        # transform each row into OSCAL equivalent\n        for row in xlsx_helper.row_generator():\n            section = xlsx_helper.get(row, 'section #')\n            recommendation = xlsx_helper.get(row, 'recommendation #')\n            title = xlsx_helper.get(row, 'title')\n            # init\n            props = []\n            parts = []\n            links = []\n            # props\n            self._add_property(xlsx_helper, props, row, 'profile')\n            self._add_property(xlsx_helper, props, row, 'assessment status')\n            if recommendation is None:\n                frag = section\n            else:\n                frag = recommendation\n            # parts\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_smt', row, 'statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rat', row, 'rational statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_imp', row, 'impact statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rem', row, 'remediation procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_aud', row, 'audit procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_inf', row, 'additional information')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_ctl', row, 'CIS Controls')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_1v8', row, 'CIS Safeguards 1 (v8)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_2v8', row, 'CIS Safeguards 2 (v8)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_3v8', row, 'CIS Safeguards 3 (v8)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_1v7', row, 'CIS Safeguards 1 (v7)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_2v7', row, 'CIS Safeguards 2 (v7)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_3v7', row, 'CIS Safeguards 3 (v7)')\n            # group or control\n            if recommendation is None:\n                catalog_helper.add_group(section, title, props, parts)\n            else:\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG3')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG3')\n                self._add_links(xlsx_helper, catalog_helper, links, row, 'references')\n                catalog_helper.add_control(section, recommendation, title, props, parts, links)\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.ns","title":"ns","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.cis-xlsx-to-oscal-catalog]:')\n    text1 = '  input-file             = '\n    text2 = '(required) path to read the compliance-as-code .xlsx spread sheet file.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = '(required) location to write the generated catalog.json file.'\n    logger.info(text1 + text2)\n    text1 = '  title                  = '\n    text2 = '(required) title of the CIS catalog.'\n    logger.info(text1 + text2)\n    text1 = '  version                = '\n    text2 = '(required) version of the CIS catalog.'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite       = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper","title":" XlsxHelper ","text":"

                                    Xlsx Helper common functions and assistance navigating spread sheet.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    class XlsxHelper:\n\"\"\"Xlsx Helper common functions and assistance navigating spread sheet.\"\"\"\n\n    def __init__(self, file: str) -> None:\n\"\"\"Initialize.\"\"\"\n        self._spread_sheet = file\n        self._wb = load_workbook(self._spread_sheet)\n        sheet_candidates = ['Combined Profiles', 'Combined']\n        self._sheet_name = None\n        for sheet_candidate in sheet_candidates:\n            if sheet_candidate in self._wb.sheetnames:\n                self._sheet_name = sheet_candidate\n                break\n        if not self._sheet_name:\n            raise RuntimeError(f'{file} missing one of {sheet_candidates} sheet')\n        self._work_sheet = self._wb[self._sheet_name]\n        self._mapper()\n        self._key_to_col_map = {'statement': 'description'}\n\n    def is_ocp(self) -> bool:\n\"\"\"Check if sheet is for OCP.\"\"\"\n        return self._sheet_name == 'Combined Profiles'\n\n    def _normalize(self, name: str) -> str:\n\"\"\"Normalize.\"\"\"\n        return name.lower()\n\n    def _translate(self, name: str) -> str:\n\"\"\"Translate name key to column name.\"\"\"\n        return self._key_to_col_map.get(name, name)\n\n    def _mapper(self) -> None:\n\"\"\"Map columns heading names to column numbers.\"\"\"\n        self._col_name_to_number = {}\n        cols = self._work_sheet.max_column\n        row = 1\n        for col in range(row, cols):\n            cell = self._work_sheet.cell(row, col)\n            if cell.value:\n                name = self._normalize(cell.value)\n                self._col_name_to_number[name] = col\n\n    def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until max reached.\"\"\"\n        row = 2\n        while row <= self._work_sheet.max_row:\n            yield row\n            row += 1\n\n    def get(self, row: int, name: str) -> str:\n\"\"\"Get cell value for given row and column name.\"\"\"\n        nname = self._normalize(name)\n        cname = self._translate(nname)\n        col = self._col_name_to_number[cname]\n        cell = self._work_sheet.cell(row, col)\n        return cell.value\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.__init__","title":"__init__(self, file) special","text":"

                                    Initialize.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def __init__(self, file: str) -> None:\n\"\"\"Initialize.\"\"\"\n    self._spread_sheet = file\n    self._wb = load_workbook(self._spread_sheet)\n    sheet_candidates = ['Combined Profiles', 'Combined']\n    self._sheet_name = None\n    for sheet_candidate in sheet_candidates:\n        if sheet_candidate in self._wb.sheetnames:\n            self._sheet_name = sheet_candidate\n            break\n    if not self._sheet_name:\n        raise RuntimeError(f'{file} missing one of {sheet_candidates} sheet')\n    self._work_sheet = self._wb[self._sheet_name]\n    self._mapper()\n    self._key_to_col_map = {'statement': 'description'}\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.get","title":"get(self, row, name)","text":"

                                    Get cell value for given row and column name.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def get(self, row: int, name: str) -> str:\n\"\"\"Get cell value for given row and column name.\"\"\"\n    nname = self._normalize(name)\n    cname = self._translate(nname)\n    col = self._col_name_to_number[cname]\n    cell = self._work_sheet.cell(row, col)\n    return cell.value\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.is_ocp","title":"is_ocp(self)","text":"

                                    Check if sheet is for OCP.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def is_ocp(self) -> bool:\n\"\"\"Check if sheet is for OCP.\"\"\"\n    return self._sheet_name == 'Combined Profiles'\n
                                    "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.row_generator","title":"row_generator(self)","text":"

                                    Generate rows until max reached.

                                    Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                    def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until max reached.\"\"\"\n    row = 2\n    while row <= self._work_sheet.max_row:\n        yield row\n        row += 1\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/","title":"csv_to_oscal_cd","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd","title":"trestle.tasks.csv_to_oscal_cd","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.ADJUSTED_RISK_RATING","title":"ADJUSTED_RISK_RATING","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CHECK_DESCRIPTION","title":"CHECK_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CHECK_ID","title":"CHECK_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.COMPONENT_DESCRIPTION","title":"COMPONENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.COMPONENT_TITLE","title":"COMPONENT_TITLE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.COMPONENT_TYPE","title":"COMPONENT_TYPE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CONTROL_ID_LIST","title":"CONTROL_ID_LIST","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.FETCHER_DESCRIPTION","title":"FETCHER_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.FETCHER_ID","title":"FETCHER_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.HEADER_DECORATION_CHAR","title":"HEADER_DECORATION_CHAR","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.NAMESPACE","title":"NAMESPACE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.ORIGINAL_RISK_RATING","title":"ORIGINAL_RISK_RATING","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER","title":"PARAMETER","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_DESCRIPTION","title":"PARAMETER_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_ID","title":"PARAMETER_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_VALUE_ALTERNATIVES","title":"PARAMETER_VALUE_ALTERNATIVES","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_VALUE_DEFAULT","title":"PARAMETER_VALUE_DEFAULT","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PROFILE_DESCRIPTION","title":"PROFILE_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PROFILE_SOURCE","title":"PROFILE_SOURCE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.RISK_ADJUSTMENT","title":"RISK_ADJUSTMENT","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.RULE_DESCRIPTION","title":"RULE_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.RULE_ID","title":"RULE_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.Row","title":"Row","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.prefix_rule_set","title":"prefix_rule_set","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.validation","title":"validation","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn","title":" CsvColumn ","text":"

                                    CsvColumn.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    class CsvColumn():\n\"\"\"CsvColumn.\"\"\"\n\n    _columns_required = [\n        f'{COMPONENT_TITLE}',\n        f'{COMPONENT_DESCRIPTION}',\n        f'{COMPONENT_TYPE}',\n        f'{RULE_ID}',\n        f'{RULE_DESCRIPTION}',\n        f'{PROFILE_SOURCE}',\n        f'{PROFILE_DESCRIPTION}',\n        f'{CONTROL_ID_LIST}',\n        f'{NAMESPACE}',\n    ]\n\n    _columns_required_validation = [\n        f'{COMPONENT_TITLE}',\n        f'{COMPONENT_DESCRIPTION}',\n        f'{COMPONENT_TYPE}',\n        f'{RULE_ID}',\n        f'{NAMESPACE}',\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n    ]\n\n    _columns_optional = [\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n        f'{ORIGINAL_RISK_RATING}',\n        f'{ADJUSTED_RISK_RATING}',\n        f'{RISK_ADJUSTMENT}',\n    ]\n\n    _columns_parameter = [\n        f'{PARAMETER_ID}',\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n        f'{PARAMETER_VALUE_DEFAULT}',\n    ]\n\n    _columns_ordered = _columns_required + _columns_parameter + _columns_optional\n\n    @staticmethod\n    def get_order(column_name: str) -> int:\n\"\"\"Get order for column_name.\"\"\"\n        rval = sys.maxsize\n        if column_name in CsvColumn._columns_ordered:\n            rval = CsvColumn._columns_ordered.index(column_name)\n        return rval\n\n    @staticmethod\n    def is_column_name_required(name: str) -> bool:\n\"\"\"Is column name required.\"\"\"\n        return name in (CsvColumn._columns_required + CsvColumn._columns_required_validation)\n\n    @staticmethod\n    def is_column_name_optional(name: str) -> bool:\n\"\"\"Is column name optional.\"\"\"\n        return name in (CsvColumn._columns_optional)\n\n    @staticmethod\n    def is_column_name_parameter(name: str) -> bool:\n\"\"\"Is column name parameter.\"\"\"\n        for cname in CsvColumn._columns_parameter:\n            if name.startswith(cname):\n                return True\n        return False\n\n    @staticmethod\n    def get_required_column_names() -> List[str]:\n\"\"\"Get required column names.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_required\n        return rval\n\n    @staticmethod\n    def get_optional_column_names() -> List[str]:\n\"\"\"Get optional column names.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_optional\n        return rval\n\n    @staticmethod\n    def get_parameter_column_names() -> List[str]:\n\"\"\"Get parameter column names.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_parameters\n        return rval\n\n    @staticmethod\n    def get_required_column_names_validation() -> List[str]:\n\"\"\"Get required column names validation.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_required_validation\n        return rval\n\n    _rule_property_column_names = [\n        f'{RULE_ID}',\n        f'{RULE_DESCRIPTION}',\n        f'{PARAMETER_ID}',\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n        f'{ORIGINAL_RISK_RATING}',\n        f'{ADJUSTED_RISK_RATING}',\n        f'{RISK_ADJUSTMENT}',\n    ]\n\n    @staticmethod\n    def get_rule_property_column_names() -> List[str]:\n\"\"\"Get rule property column names.\"\"\"\n        return CsvColumn._rule_property_column_names\n\n    # columns required which do not become properties\n    _columns_required_filtered = [\n        f'{COMPONENT_TITLE}',\n        f'{COMPONENT_DESCRIPTION}',\n        f'{COMPONENT_TYPE}',\n        f'{PROFILE_SOURCE}',\n        f'{PROFILE_DESCRIPTION}',\n        f'{CONTROL_ID_LIST}',\n        f'{NAMESPACE}',\n    ]\n\n    # optional columns which do not become properties, initially\n    _columns_optional_filtered = []\n\n    _columns_filtered = _columns_required_filtered + _columns_optional_filtered\n\n    @staticmethod\n    def get_filtered_required_column_names() -> List[str]:\n\"\"\"Get filtered required column names.\"\"\"\n        rval = []\n        for column_name in CsvColumn.get_required_column_names():\n            if column_name not in CsvColumn._columns_filtered:\n                rval.append(column_name)\n        return rval\n\n    @staticmethod\n    def get_filtered_optional_column_names() -> List[str]:\n\"\"\"Get filtered optional column names.\"\"\"\n        rval = []\n        for column_name in CsvColumn.get_optional_column_names():\n            if column_name not in CsvColumn._columns_filtered:\n                rval.append(column_name)\n        return rval\n\n    _check_property_column_names = [\n        f'{RULE_ID}',\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n    ]\n\n    @staticmethod\n    def get_check_property_column_names() -> List[str]:\n\"\"\"Get check property column names.\"\"\"\n        return CsvColumn._check_property_column_names\n\n    # optional columns which do become properties, afterwards\n    _columns_parameters = [\n        f'{PARAMETER_ID}',\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n    ]\n\n    # optional columns which require Param_Id be present in the row\n    _columns_parameters_dependent = [\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n        f'{PARAMETER_VALUE_DEFAULT}',\n    ]\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_check_property_column_names","title":"get_check_property_column_names() staticmethod","text":"

                                    Get check property column names.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_check_property_column_names() -> List[str]:\n\"\"\"Get check property column names.\"\"\"\n    return CsvColumn._check_property_column_names\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_filtered_optional_column_names","title":"get_filtered_optional_column_names() staticmethod","text":"

                                    Get filtered optional column names.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_filtered_optional_column_names() -> List[str]:\n\"\"\"Get filtered optional column names.\"\"\"\n    rval = []\n    for column_name in CsvColumn.get_optional_column_names():\n        if column_name not in CsvColumn._columns_filtered:\n            rval.append(column_name)\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_filtered_required_column_names","title":"get_filtered_required_column_names() staticmethod","text":"

                                    Get filtered required column names.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_filtered_required_column_names() -> List[str]:\n\"\"\"Get filtered required column names.\"\"\"\n    rval = []\n    for column_name in CsvColumn.get_required_column_names():\n        if column_name not in CsvColumn._columns_filtered:\n            rval.append(column_name)\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_optional_column_names","title":"get_optional_column_names() staticmethod","text":"

                                    Get optional column names.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_optional_column_names() -> List[str]:\n\"\"\"Get optional column names.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_optional\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_order","title":"get_order(column_name) staticmethod","text":"

                                    Get order for column_name.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_order(column_name: str) -> int:\n\"\"\"Get order for column_name.\"\"\"\n    rval = sys.maxsize\n    if column_name in CsvColumn._columns_ordered:\n        rval = CsvColumn._columns_ordered.index(column_name)\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_parameter_column_names","title":"get_parameter_column_names() staticmethod","text":"

                                    Get parameter column names.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_parameter_column_names() -> List[str]:\n\"\"\"Get parameter column names.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_parameters\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_required_column_names","title":"get_required_column_names() staticmethod","text":"

                                    Get required column names.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_required_column_names() -> List[str]:\n\"\"\"Get required column names.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_required\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_required_column_names_validation","title":"get_required_column_names_validation() staticmethod","text":"

                                    Get required column names validation.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_required_column_names_validation() -> List[str]:\n\"\"\"Get required column names validation.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_required_validation\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_rule_property_column_names","title":"get_rule_property_column_names() staticmethod","text":"

                                    Get rule property column names.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef get_rule_property_column_names() -> List[str]:\n\"\"\"Get rule property column names.\"\"\"\n    return CsvColumn._rule_property_column_names\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.is_column_name_optional","title":"is_column_name_optional(name) staticmethod","text":"

                                    Is column name optional.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef is_column_name_optional(name: str) -> bool:\n\"\"\"Is column name optional.\"\"\"\n    return name in (CsvColumn._columns_optional)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.is_column_name_parameter","title":"is_column_name_parameter(name) staticmethod","text":"

                                    Is column name parameter.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef is_column_name_parameter(name: str) -> bool:\n\"\"\"Is column name parameter.\"\"\"\n    for cname in CsvColumn._columns_parameter:\n        if name.startswith(cname):\n            return True\n    return False\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.is_column_name_required","title":"is_column_name_required(name) staticmethod","text":"

                                    Is column name required.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    @staticmethod\ndef is_column_name_required(name: str) -> bool:\n\"\"\"Is column name required.\"\"\"\n    return name in (CsvColumn._columns_required + CsvColumn._columns_required_validation)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition","title":" CsvToOscalComponentDefinition (TaskBase) ","text":"

                                    Task to create OSCAL ComponentDefinition json.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    class CsvToOscalComponentDefinition(TaskBase):\n\"\"\"\n    Task to create OSCAL ComponentDefinition json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'csv-to-oscal-cd'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task csv-to-oscal-cd.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        name = self.name\n        oscal_name = 'component_definition'\n        #\n        logger.info(f'Help information for {name} task.')\n        logger.info('')\n        logger.info(f'Purpose: From csv produce OSCAL {oscal_name} file.')\n        logger.info('')\n        logger.info('')\n        logger.info(f'Configuration flags sit under [task.{name}]:')\n        text1 = '  title                = '\n        text2 = '(required) the component definition title.'\n        logger.info(text1 + text2)\n        text1 = '  version              = '\n        text2 = '(required) the component definition version.'\n        logger.info(text1 + text2)\n        text1 = '  csv-file             = '\n        text2 = '(required) the path of the csv file.'\n        text3 = ' [1st row are column headings; 2nd row are column descriptions; 3rd row and beyond is data]'\n        logger.info(text1 + text2 + text3)\n        text1 = '  required columns:      '\n        for text2 in CsvColumn.get_required_column_names():\n            if text2 in [f'{RULE_DESCRIPTION}', f'{PROFILE_SOURCE}', f'{PROFILE_DESCRIPTION}', f'{CONTROL_ID_LIST}']:\n                text2 += ' (see note 1)'\n            logger.info(text1 + '$$' + text2)\n            text1 = '                         '\n        text1 = '  optional columns:      '\n        for text2 in CsvColumn.get_optional_column_names():\n            if text2 in [f'{ORIGINAL_RISK_RATING}', f'{ADJUSTED_RISK_RATING}', f'{RISK_ADJUSTMENT}']:\n                text2 += ' (see note 1)'\n            else:\n                text2 += ' (see note 2)'\n            logger.info(text1 + '$' + text2)\n            text1 = '                         '\n        for text2 in CsvColumn.get_parameter_column_names():\n            text2 += ' (see notes 1, 4)'\n            logger.info(text1 + '$' + text2)\n            text1 = '                         '\n        text1 = '  comment columns:       '\n        text2 = 'Informational (see note 3)'\n        logger.info(text1 + '#' + text2)\n        text1 = '  output-dir           = '\n        text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n        logger.info(text1 + text2)\n        text1 = '  component-definition = '\n        text2 = '(optional) the path of the existing component-definition OSCAL .json file.'\n        logger.info(text1 + text2)\n        text1 = '  class.column-name    = '\n        text2 = f'(optional) the class to associate with the specified column name, e.g. class.{RULE_ID} = scc_class'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite     = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n        text1 = '  validate-controls    = '\n        text2 = '(optional) on, warn, or off [default]; validate controls exist in resolved profile.'\n        logger.info(text1 + text2)\n        # Notes\n        text1 = ''\n        text2 = ''\n        logger.info(text1 + text2)\n        text1 = 'Notes: '\n        text2 = '[1] column is ignored for validation component type'\n        logger.info(text1 + text2)\n        text1 = '       '\n        text2 = '[2] column is required for validation component type'\n        logger.info(text1 + text2)\n        text1 = '       '\n        text2 = '[3] column name starting with # causes column to be ignored'\n        logger.info(text1 + text2)\n        text1 = '       '\n        text2 = '[4] additional parameters are specified by adding a common suffix per set'\n        text3 = f', for example: {PARAMETER_ID}_1, {PARAMETER_DESCRIPTION}_1, ...{PARAMETER_ID}_2...'\n        logger.info(text1 + text2 + text3)\n\n    def configure(self) -> bool:\n\"\"\"Configure.\"\"\"\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n        # config verbosity\n        self._quiet = self._config.get('quiet', False)\n        self._verbose = not self._quiet\n        # title\n        self._title = self._config.get('title')\n        if self._title is None:\n            logger.warning('config missing \"title\"')\n            return False\n        # version\n        self._version = self._config.get('version')\n        if self._version is None:\n            logger.warning('config missing \"version\"')\n            return False\n        # config csv\n        self._csv_file = self._config.get('csv-file')\n        if self._csv_file is None:\n            logger.warning('config missing \"csv-file\"')\n            return False\n        self._csv_path = pathlib.Path(self._csv_file)\n        if not self._csv_path.exists():\n            logger.warning('\"csv-file\" not found')\n            return False\n        # announce csv\n        if self._verbose:\n            logger.info(f'input: {self._csv_file}')\n        # config cd\n        self._cd_path = None\n        self._cd_file = self._config.get('component-definition')\n        if self._cd_file is not None:\n            self._cd_path = pathlib.Path(self._cd_file)\n            if not self._cd_path.exists():\n                logger.warning('\"component-definition\" not found')\n                return False\n        # workspace\n        self._workspace = os.getcwd()\n        # validate_controls\n        self._validate_controls = self._config.get('validate-controls', 'off')\n        return True\n\n    def get_class(self, name: str) -> str:\n\"\"\"Get class value for specified name from config.\"\"\"\n        key = f'class.{name}'\n        return self._config.get(key)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.error(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Execute path core.\"\"\"\n        if not self.configure():\n            return TaskOutcome('failure')\n        # config output\n        odir = self._config.get('output-dir')\n        opth = pathlib.Path(odir)\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'component-definition.json'\n        ofile = opth / oname\n        if not self._overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # fetch existing component-definition, if any\n        self._cd_mgr = _CdMgr(self._cd_path, self._title, self._timestamp, self._version)\n        # fetch csv\n        self._csv_mgr = _CsvMgr(self._csv_path)\n        # create resolved profile -> catalog helper\n        profile_list = self._csv_mgr.get_profile_list()\n        self._resolved_profile_catalog_helper = _ResolvedProfileCatalogHelper(profile_list, self._workspace)\n        self._unresolved_controls = []\n        # calculate deletion, addition & modification rule lists\n        rules = self._calculate_rules()\n        # calculate deletion, addition & modification set-parameter lists\n        set_params = self._calculate_set_params(rules[2])\n        # calculate deletion, addition & modification control mapping lists\n        control_mappings = self._calculate_control_mappings(rules[2])\n        # rule set manager\n        self._rule_set_id_mgr = _RuleSetIdMgr(self._cd_mgr.get_max_rule_set_number(), len(rules[1]))\n        # rule additions, deletions & modifications (by row)\n        self.rules_del(rules[0])\n        self.rules_add(rules[1])\n        self.rules_mod(rules[2])\n        # set-parameters additions, deletions & modifications (by row)\n        self.set_params_del(set_params[0])\n        self.set_params_add(set_params[1])\n        self.set_params_mod(set_params[2])\n        # control mappings additions, deletions & modifications (by row)\n        self.control_mappings_del(control_mappings[0])\n        self.control_mappings_add(control_mappings[1])\n        # note: control mappings mod is currently not possible\n        # note: add/del user columns not currently supported\n        if len(self._unresolved_controls) > 0:\n            text = f'Unresolved controls: {self._unresolved_controls}'\n            if self._validate_controls == 'warn':\n                logger.warning(text)\n            elif self._validate_controls == 'on':\n                raise RuntimeError(text)\n        # prepare new/revised component definition\n        component_definition = self._cd_mgr.get_component_definition()\n        # write OSCAL ComponentDefinition to file\n        if self._verbose:\n            logger.info(f'output: {ofile}')\n        component_definition.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _calculate_rules(self) -> tuple:\n\"\"\"Calculate rules add, delete, modify.\"\"\"\n        cd_rules = self._cd_mgr.get_rule_keys()\n        csv_rules = self._csv_mgr.get_rule_keys()\n        del_rules = []\n        add_rules = []\n        mod_rules = []\n        for key in cd_rules:\n            if key in csv_rules:\n                continue\n            else:\n                del_rules.append(key)\n                logger.debug(f'rules del: {key}')\n        for key in csv_rules:\n            if key in cd_rules:\n                mod_rules.append(key)\n                logger.debug(f'rules mod: {key}')\n            else:\n                add_rules.append(key)\n                logger.debug(f'rules add: {key}')\n        return (del_rules, add_rules, mod_rules)\n\n    def _calculate_set_params(self, mod_rules: List) -> tuple:\n\"\"\"Calculate set parameters add, delete, modify.\"\"\"\n        cd_set_params = self._cd_mgr.get_set_params_keys()\n        csv_set_params = self._csv_mgr.get_set_params_keys()\n        del_set_params = []\n        add_set_params = []\n        mod_set_params = []\n        for key in cd_set_params:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in csv_set_params:\n                continue\n            else:\n                del_set_params.append(key)\n                logger.debug(f'params del: {key}')\n        for key in csv_set_params:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in cd_set_params:\n                mod_set_params.append(key)\n                logger.debug(f'params mod: {key}')\n            else:\n                add_set_params.append(key)\n                logger.debug(f'params add: {key}')\n        return (del_set_params, add_set_params, mod_set_params)\n\n    def _calculate_control_mappings(self, mod_rules: List) -> tuple:\n\"\"\"Calculate control mappings add, delete, modify.\"\"\"\n        cd_controls = self._cd_mgr.get_control_keys()\n        csv_controls = self._csv_mgr.get_control_keys()\n        del_control_mappings = []\n        add_control_mappings = []\n        mod_control_mappings = []\n        for key in cd_controls:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in csv_controls:\n                continue\n            else:\n                del_control_mappings.append(key)\n                logger.debug(f'ctl-maps del: {key}')\n        for key in csv_controls:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in cd_controls:\n                mod_control_mappings.append(key)\n                logger.debug(f'ctl-maps mod: {key}')\n            else:\n                add_control_mappings.append(key)\n                logger.debug(f'ctl-maps add: {key}')\n        return (del_control_mappings, add_control_mappings, mod_control_mappings)\n\n    def _get_namespace(self, rule_key: tuple) -> str:\n\"\"\"Get namespace.\"\"\"\n        return self._csv_mgr.get_value(rule_key, NAMESPACE).strip()\n\n    def _get_prop_name(self, column_name: str) -> str:\n\"\"\"Get property name.\"\"\"\n        return column_name.lstrip('$')\n\n    def rules_del(self, del_rules: List[str]) -> None:\n\"\"\"Delete rules.\"\"\"\n        for tokens in del_rules:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            description = ''\n            # component\n            component = self._cd_mgr.get_component(component_title, component_type, description)\n            # props\n            component.props = self._delete_rule_props(component, rule_id)\n\n    def _delete_rule_props(self, component: DefinedComponent, rule_id: str) -> List[Property]:\n\"\"\"Delete rule props.\"\"\"\n        props = []\n        rule_set = _RuleSetHelper.get_rule_set(component.props, rule_id)\n        for prop in component.props:\n            if prop.remarks != rule_set:\n                props.append(prop)\n            elif prop.name in self._csv_mgr.get_parameter_id_column_names():\n                self._delete_rule_set_parameter(component, prop.value)\n            elif prop.name == RULE_ID:\n                self._delete_rule_implemented_requirement(component, prop.value)\n        return props\n\n    def _control_implementation_generator(\n        self, control_implementations: List[ControlImplementation]\n    ) -> Iterator[ControlImplementation]:\n\"\"\"Control implementation generator.\"\"\"\n        if control_implementations:\n            for control_implementation in control_implementations:\n                yield control_implementation\n\n    def _set_parameter_generator(self, set_parameters: List[SetParameter]) -> Iterator[SetParameter]:\n\"\"\"Set parameter generator.\"\"\"\n        if set_parameters:\n            for set_parameter in set_parameters:\n                yield set_parameter\n\n    def _implemented_requirement_generator(\n        self, implemented_requirements: List[ImplementedRequirement]\n    ) -> Iterator[ImplementedRequirement]:\n\"\"\"Implemented-requirement generator.\"\"\"\n        if implemented_requirements:\n            for implemented_requirement in implemented_requirements:\n                yield implemented_requirement\n\n    def _delete_rule_set_parameter(self, component: DefinedComponent, parameter_id: str) -> None:\n\"\"\"Delete rule set-parameter.\"\"\"\n        control_implementations = component.control_implementations\n        for control_implementation in self._control_implementation_generator(control_implementations):\n            if control_implementation.set_parameters:\n                set_parameters = control_implementation.set_parameters\n                control_implementation.set_parameters = []\n                for set_parameter in set_parameters:\n                    if set_parameter.param_id != parameter_id:\n                        _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n                if not len(control_implementation.set_parameters):\n                    control_implementation.set_parameters = None\n\n    def _delete_rule_implemented_requirement(self, component: DefinedComponent, rule_id: str) -> None:\n\"\"\"Delete rule implemented_requirement.\"\"\"\n        control_implementations = component.control_implementations\n        component.control_implementations = []\n        for control_implementation in self._control_implementation_generator(control_implementations):\n            if control_implementation.implemented_requirements:\n                implemented_requirements = control_implementation.implemented_requirements\n                control_implementation.implemented_requirements = []\n                for implemented_requirement in implemented_requirements:\n                    self._delete_ir_props(implemented_requirement, rule_id)\n                    self._delete_ir_statements(implemented_requirement, rule_id)\n                    if len(as_list(implemented_requirement.props)) or len(as_list(implemented_requirement.statements)):\n                        control_implementation.implemented_requirements.append(implemented_requirement)\n            if len(as_list(control_implementation.implemented_requirements)):\n                component.control_implementations.append(control_implementation)\n\n    def _delete_ir_statements(self, implemented_requirement: ImplementedRequirement, rule_id: str) -> None:\n\"\"\"Delete implemented-requirement statements.\"\"\"\n        if implemented_requirement.statements:\n            statements = implemented_requirement.statements\n            implemented_requirement.statements = []\n            for statement in statements:\n                statement.props = self._delete_props(statement.props, rule_id)\n                if not len(statement.props):\n                    statement.props = None\n                if statement.props:\n                    implemented_requirement.statements.append(statement)\n            if not len(implemented_requirement.statements):\n                implemented_requirement.statements = None\n\n    def _delete_ir_props(self, implemented_requirement: ImplementedRequirement, rule_id: str) -> None:\n\"\"\"Delete implemented-requirement props.\"\"\"\n        if implemented_requirement.props:\n            implemented_requirement.props = self._delete_props(implemented_requirement.props, rule_id)\n            if not len(implemented_requirement.props):\n                implemented_requirement.props = None\n\n    def _delete_props(self, props: List[Property], rule_id: str) -> List[property]:\n\"\"\"Delete props.\"\"\"\n        rval = []\n        if props:\n            for prop in props:\n                if prop.name == RULE_ID and prop.value == rule_id:\n                    continue\n                rval.append(prop)\n        return rval\n\n    def rules_add(self, add_rules: List[str]) -> None:\n\"\"\"Add rules.\"\"\"\n        for rule_key in add_rules:\n            component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n            component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n            component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n            # component\n            component = self._cd_mgr.get_component(component_title, component_type, component_description)\n            # props\n            component.props = as_list(component.props)\n            component.props = component.props + self._create_rule_props(rule_key)\n            # additional props, when not validation component\n            if not self._is_validation(rule_key):\n                # control implementation\n                source = self._csv_mgr.get_value(rule_key, PROFILE_SOURCE)\n                description = self._csv_mgr.get_value(rule_key, PROFILE_DESCRIPTION)\n                control_implementation = self._get_control_implementation(component, source, description)\n                # set-parameters\n                set_parameters = self._create_set_parameters(rule_key)\n                if set_parameters:\n                    control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n                    _OscalHelper.add_set_parameters(control_implementation.set_parameters, set_parameters)\n                # control-mappings\n                control_mappings = self._csv_mgr.get_value(rule_key, CONTROL_ID_LIST).split()\n                self._add_rule_prop(control_implementation, control_mappings, rule_key)\n\n    def _is_validation(self, rule_key: tuple) -> bool:\n\"\"\"Check for validation component.\"\"\"\n        component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n        return component_type.lower() == validation\n\n    def _add_rule_prop(\n        self, control_implementation: ControlImplementation, control_mappings: List[str], rule_key: tuple\n    ) -> None:\n\"\"\"Add rule prop.\"\"\"\n        namespace = self._get_namespace(rule_key)\n        for control_mapping in control_mappings:\n            control_id = derive_control_id(control_mapping)\n            implemented_requirement = self._get_implemented_requirement(control_implementation, control_id)\n            # create rule implementation (as property)\n            name = RULE_ID\n            prop = Property(\n                name=name,\n                value=self._csv_mgr.get_value(rule_key, name),\n                ns=namespace,\n                class_=self.get_class(name),\n            )\n            part_id = derive_part_id(control_mapping)\n            if part_id is None:\n                implemented_requirement.props = as_list(implemented_requirement.props)\n                implemented_requirement.props.append(prop)\n            else:\n                statement = self._get_statement(implemented_requirement, part_id)\n                statement.props.append(prop)\n\n    def _create_rule_props(self, rule_key: tuple) -> List[Property]:\n\"\"\"Create rule props.\"\"\"\n        rule_set = self._rule_set_id_mgr.get_next_rule_set_id()\n        row_number = self._csv_mgr.get_row_number(rule_key)\n        rule_set_mgr = _RuleSetMgr(row_number, rule_set)\n        namespace = self._get_namespace(rule_key)\n        if self._is_validation(rule_key):\n            column_names = CsvColumn.get_check_property_column_names()\n        else:\n            column_names = CsvColumn.get_rule_property_column_names()\n        # req'd & optional props\n        for column_name in column_names:\n            prop_name = self._get_prop_name(column_name)\n            prop_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            rule_set_mgr.add_prop(prop_name, prop_value, namespace, self.get_class(prop_name))\n        if not self._is_validation(rule_key):\n            # parameter columns\n            column_names = self._csv_mgr.get_parameter_column_names()\n            for column_name in column_names:\n                prop_name = self._get_prop_name(column_name)\n                prop_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n                rule_set_mgr.add_prop(prop_name, prop_value, namespace, self.get_class(prop_name))\n        # user props\n        column_names = self._csv_mgr.get_user_column_names()\n        for column_name in column_names:\n            if column_name.startswith('#'):\n                continue\n            prop_name = self._get_prop_name(column_name)\n            prop_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            rule_set_mgr.add_prop(prop_name, prop_value, namespace, self.get_class(prop_name))\n        return rule_set_mgr.get_props()\n\n    def _get_control_implementation(\n        self, component: DefinedComponent, source: str, description: str\n    ) -> ControlImplementation:\n\"\"\"Find or create control implementation.\"\"\"\n        component.control_implementations = as_list(component.control_implementations)\n        for control_implementation in component.control_implementations:\n            if control_implementation.source == source and control_implementation.description == description:\n                return control_implementation\n        control_implementation = ControlImplementation(\n            uuid=str(uuid.uuid4()), source=source, description=description, implemented_requirements=[]\n        )\n        component.control_implementations.append(control_implementation)\n        return control_implementation\n\n    def _str_to_list(self, value: str) -> List[str]:\n\"\"\"Transform string to list.\"\"\"\n        rval = []\n        if ',' in value:\n            values = value.split(',')\n            # remove leading/trailing whitespace\n            for v in values:\n                rval.append(v.strip())\n        else:\n            rval.append(value)\n        return rval\n\n    def _create_set_parameters(self, rule_key: tuple) -> List[SetParameter]:\n\"\"\"Create set parameters.\"\"\"\n        set_parameters = []\n        for parameter_id_column_name in self._csv_mgr.get_parameter_id_column_names():\n            suffix = parameter_id_column_name.replace(PARAMETER_ID, '')\n            parameter_value_default_column_name = f'{PARAMETER_VALUE_DEFAULT}{suffix}'\n            name = self._csv_mgr.get_value(rule_key, parameter_id_column_name)\n            value = self._csv_mgr.get_value(rule_key, parameter_value_default_column_name)\n            if name and value:\n                try:\n                    values = self._str_to_list(value)\n                    set_parameter = SetParameter(\n                        param_id=name,\n                        values=values,\n                    )\n                    set_parameters.append(set_parameter)\n                except Exception:\n                    row_number = self._csv_mgr.get_row_number(rule_key)\n                    text = (\n                        f'row {row_number}: \"{name}\" is invalid for column {parameter_id_column_name} '\n                        f'and/or \"{\",\".join(values)}\" is invalid for column {parameter_value_default_column_name}'\n                    )\n                    raise RuntimeError(text)\n            elif name:\n                row_number = self._csv_mgr.get_row_number(rule_key)\n                text = f'row \"{row_number}\" missing value for \"{parameter_value_default_column_name}\"'\n                logger.debug(text)\n        return set_parameters\n\n    def _get_implemented_requirement(\n        self, control_implementation: ControlImplementation, control_id: str\n    ) -> ImplementedRequirement:\n\"\"\"Find or create implemented requirement.\"\"\"\n        if self._validate_controls != 'off':\n            if not self._resolved_profile_catalog_helper.validate(control_id):\n                if control_id not in self._unresolved_controls:\n                    self._unresolved_controls.append(control_id)\n        for implemented_requirement in control_implementation.implemented_requirements:\n            if implemented_requirement.control_id == control_id:\n                return implemented_requirement\n        implemented_requirement = ImplementedRequirement(\n            uuid=str(uuid.uuid4()),\n            control_id=control_id,\n            description='',\n        )\n        control_implementation.implemented_requirements.append(implemented_requirement)\n        return implemented_requirement\n\n    def _get_statement(self, implemented_requirement: ImplementedRequirement, part_id: str) -> Statement:\n\"\"\"Find or create statement.\"\"\"\n        implemented_requirement.statements = as_list(implemented_requirement.statements)\n        for statement in implemented_requirement.statements:\n            if statement.statement_id == part_id:\n                return statement\n        statement = Statement(\n            uuid=str(uuid.uuid4()),\n            statement_id=part_id,\n            description='',\n            props=[],\n        )\n        implemented_requirement.statements.append(statement)\n        return statement\n\n    def rules_mod(self, mod_rules: List[str]) -> None:\n\"\"\"Modify rules.\"\"\"\n        for rule_key in mod_rules:\n            component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n            component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n            component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n            # component\n            component = self._cd_mgr.get_component(component_title, component_type, component_description)\n            # props\n            component.props = self._modify_rule_props(component, rule_key)\n\n    def _modify_rule_props(self, component: DefinedComponent, rule_key: tuple) -> List[Property]:\n\"\"\"Modify rule props.\"\"\"\n        rule_id = self._csv_mgr.get_value(rule_key, RULE_ID)\n        rule_set = _RuleSetHelper.get_rule_set(component.props, rule_id)\n        rule_ns = self._csv_mgr.get_value(rule_key, NAMESPACE)\n        column_names = CsvColumn.get_filtered_required_column_names() + CsvColumn.get_filtered_optional_column_names()\n        # req'd & optional props\n        for column_name in column_names:\n            column_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            class_ = self.get_class(column_name)\n            self._cd_mgr.update_rule_definition(component, rule_set, column_name, column_value, rule_ns, class_)\n        # parameter columns\n        column_names = self._csv_mgr.get_parameter_column_names()\n        for column_name in column_names:\n            column_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            class_ = self.get_class(column_name)\n            self._cd_mgr.update_rule_definition(component, rule_set, column_name, column_value, rule_ns, class_)\n        # user props\n        column_names = self._csv_mgr.get_user_column_names()\n        for column_name in column_names:\n            column_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            self._cd_mgr.update_rule_definition(component, rule_set, column_name, column_value, rule_ns, class_)\n        return component.props\n\n    def set_params_del(self, del_set_params: List[str]) -> None:\n\"\"\"Set parameters delete.\"\"\"\n        for tokens in del_set_params:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            source = tokens[3]\n            description = tokens[4]\n            param_id = tokens[5]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            if control_implementation:\n                set_parameters = control_implementation.set_parameters\n                control_implementation.set_parameters = []\n                for set_parameter in self._set_parameter_generator(set_parameters):\n                    if set_parameter.param_id == param_id:\n                        continue\n                    _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n                if control_implementation.set_parameters == []:\n                    control_implementation.set_parameters = None\n\n    def set_params_add(self, add_set_params: List[str]) -> None:\n\"\"\"Set parameters add.\"\"\"\n        for tokens in add_set_params:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            param_id = tokens[5]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n            # add\n            rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n            values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n            set_parameter = SetParameter(\n                param_id=param_id,\n                values=values,\n            )\n            _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n\n    def set_params_mod(self, mod_set_params: List[str]) -> None:\n\"\"\"Set parameters modify.\"\"\"\n        for tokens in mod_set_params:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            param_id = tokens[5]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            if control_implementation:\n                set_parameters = control_implementation.set_parameters\n                for set_parameter in self._set_parameter_generator(set_parameters):\n                    if set_parameter.param_id != param_id:\n                        continue\n                    rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n                    values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n                    replacement = SetParameter(\n                        param_id=param_id,\n                        values=values,\n                    )\n                    if set_parameter.values == replacement.values:\n                        continue\n                    logger.debug(f'params-mod: {rule_id} {param_id} {set_parameter.values} -> {replacement.values}')\n                    set_parameter.values = replacement.values\n\n    def _control_mappings_generator(self, control_mappings: List[str]) -> Iterator[List[str]]:\n\"\"\"Control mappings generator.\"\"\"\n        for tokens in control_mappings:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            source = tokens[3]\n            description = tokens[4]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            if control_implementation:\n                yield tokens\n\n    def control_mappings_del(self, del_control_mappings: List[str]) -> None:\n\"\"\"Control mappings delete.\"\"\"\n        for tokens in self._control_mappings_generator(del_control_mappings):\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            smt_id = tokens[5]\n            control_id = derive_control_id(smt_id)\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            implemented_requirements = control_implementation.implemented_requirements\n            control_implementation.implemented_requirements = []\n            for implemented_requirement in self._implemented_requirement_generator(implemented_requirements):\n                if implemented_requirement.control_id == control_id:\n                    implemented_requirement.statements = _OscalHelper.remove_rule_statement(\n                        implemented_requirement.statements, rule_id, smt_id\n                    )\n                    implemented_requirement.props = _OscalHelper.remove_rule(implemented_requirement.props, rule_id)\n                    if len(as_list(implemented_requirement.props)) or len(as_list(implemented_requirement.statements)):\n                        control_implementation.implemented_requirements.append(implemented_requirement)\n                else:\n                    control_implementation.implemented_requirements.append(implemented_requirement)\n\n    def control_mappings_add(self, add_control_mappings: List[str]) -> None:\n\"\"\"Control mappings add.\"\"\"\n        for tokens in self._control_mappings_generator(add_control_mappings):\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            smt_id = tokens[5]\n            control_id = derive_control_id(smt_id)\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            implemented_requirement = self._get_implemented_requirement(control_implementation, control_id)\n            # namespace\n            rule_key = (tokens[0], tokens[1], tokens[2])\n            ns = self._get_namespace(rule_key)\n            # create rule implementation (as property)\n            name = RULE_ID\n            prop = Property(\n                name=name,\n                value=rule_id,\n                ns=ns,\n                class_=self.get_class(name),\n            )\n            if smt_id == control_id:\n                implemented_requirement.props = as_list(implemented_requirement.props)\n                implemented_requirement.props.append(prop)\n            else:\n                statement = self._get_statement(implemented_requirement, smt_id)\n                statement.props.append(prop)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task csv-to-oscal-cd.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task csv-to-oscal-cd.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.configure","title":"configure(self)","text":"

                                    Configure.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def configure(self) -> bool:\n\"\"\"Configure.\"\"\"\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n    # config verbosity\n    self._quiet = self._config.get('quiet', False)\n    self._verbose = not self._quiet\n    # title\n    self._title = self._config.get('title')\n    if self._title is None:\n        logger.warning('config missing \"title\"')\n        return False\n    # version\n    self._version = self._config.get('version')\n    if self._version is None:\n        logger.warning('config missing \"version\"')\n        return False\n    # config csv\n    self._csv_file = self._config.get('csv-file')\n    if self._csv_file is None:\n        logger.warning('config missing \"csv-file\"')\n        return False\n    self._csv_path = pathlib.Path(self._csv_file)\n    if not self._csv_path.exists():\n        logger.warning('\"csv-file\" not found')\n        return False\n    # announce csv\n    if self._verbose:\n        logger.info(f'input: {self._csv_file}')\n    # config cd\n    self._cd_path = None\n    self._cd_file = self._config.get('component-definition')\n    if self._cd_file is not None:\n        self._cd_path = pathlib.Path(self._cd_file)\n        if not self._cd_path.exists():\n            logger.warning('\"component-definition\" not found')\n            return False\n    # workspace\n    self._workspace = os.getcwd()\n    # validate_controls\n    self._validate_controls = self._config.get('validate-controls', 'off')\n    return True\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.control_mappings_add","title":"control_mappings_add(self, add_control_mappings)","text":"

                                    Control mappings add.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def control_mappings_add(self, add_control_mappings: List[str]) -> None:\n\"\"\"Control mappings add.\"\"\"\n    for tokens in self._control_mappings_generator(add_control_mappings):\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        smt_id = tokens[5]\n        control_id = derive_control_id(smt_id)\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        implemented_requirement = self._get_implemented_requirement(control_implementation, control_id)\n        # namespace\n        rule_key = (tokens[0], tokens[1], tokens[2])\n        ns = self._get_namespace(rule_key)\n        # create rule implementation (as property)\n        name = RULE_ID\n        prop = Property(\n            name=name,\n            value=rule_id,\n            ns=ns,\n            class_=self.get_class(name),\n        )\n        if smt_id == control_id:\n            implemented_requirement.props = as_list(implemented_requirement.props)\n            implemented_requirement.props.append(prop)\n        else:\n            statement = self._get_statement(implemented_requirement, smt_id)\n            statement.props.append(prop)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.control_mappings_del","title":"control_mappings_del(self, del_control_mappings)","text":"

                                    Control mappings delete.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def control_mappings_del(self, del_control_mappings: List[str]) -> None:\n\"\"\"Control mappings delete.\"\"\"\n    for tokens in self._control_mappings_generator(del_control_mappings):\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        smt_id = tokens[5]\n        control_id = derive_control_id(smt_id)\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        implemented_requirements = control_implementation.implemented_requirements\n        control_implementation.implemented_requirements = []\n        for implemented_requirement in self._implemented_requirement_generator(implemented_requirements):\n            if implemented_requirement.control_id == control_id:\n                implemented_requirement.statements = _OscalHelper.remove_rule_statement(\n                    implemented_requirement.statements, rule_id, smt_id\n                )\n                implemented_requirement.props = _OscalHelper.remove_rule(implemented_requirement.props, rule_id)\n                if len(as_list(implemented_requirement.props)) or len(as_list(implemented_requirement.statements)):\n                    control_implementation.implemented_requirements.append(implemented_requirement)\n            else:\n                control_implementation.implemented_requirements.append(implemented_requirement)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.execute","title":"execute(self)","text":"

                                    Provide an executed outcome.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.error(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.get_class","title":"get_class(self, name)","text":"

                                    Get class value for specified name from config.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def get_class(self, name: str) -> str:\n\"\"\"Get class value for specified name from config.\"\"\"\n    key = f'class.{name}'\n    return self._config.get(key)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    name = self.name\n    oscal_name = 'component_definition'\n    #\n    logger.info(f'Help information for {name} task.')\n    logger.info('')\n    logger.info(f'Purpose: From csv produce OSCAL {oscal_name} file.')\n    logger.info('')\n    logger.info('')\n    logger.info(f'Configuration flags sit under [task.{name}]:')\n    text1 = '  title                = '\n    text2 = '(required) the component definition title.'\n    logger.info(text1 + text2)\n    text1 = '  version              = '\n    text2 = '(required) the component definition version.'\n    logger.info(text1 + text2)\n    text1 = '  csv-file             = '\n    text2 = '(required) the path of the csv file.'\n    text3 = ' [1st row are column headings; 2nd row are column descriptions; 3rd row and beyond is data]'\n    logger.info(text1 + text2 + text3)\n    text1 = '  required columns:      '\n    for text2 in CsvColumn.get_required_column_names():\n        if text2 in [f'{RULE_DESCRIPTION}', f'{PROFILE_SOURCE}', f'{PROFILE_DESCRIPTION}', f'{CONTROL_ID_LIST}']:\n            text2 += ' (see note 1)'\n        logger.info(text1 + '$$' + text2)\n        text1 = '                         '\n    text1 = '  optional columns:      '\n    for text2 in CsvColumn.get_optional_column_names():\n        if text2 in [f'{ORIGINAL_RISK_RATING}', f'{ADJUSTED_RISK_RATING}', f'{RISK_ADJUSTMENT}']:\n            text2 += ' (see note 1)'\n        else:\n            text2 += ' (see note 2)'\n        logger.info(text1 + '$' + text2)\n        text1 = '                         '\n    for text2 in CsvColumn.get_parameter_column_names():\n        text2 += ' (see notes 1, 4)'\n        logger.info(text1 + '$' + text2)\n        text1 = '                         '\n    text1 = '  comment columns:       '\n    text2 = 'Informational (see note 3)'\n    logger.info(text1 + '#' + text2)\n    text1 = '  output-dir           = '\n    text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n    logger.info(text1 + text2)\n    text1 = '  component-definition = '\n    text2 = '(optional) the path of the existing component-definition OSCAL .json file.'\n    logger.info(text1 + text2)\n    text1 = '  class.column-name    = '\n    text2 = f'(optional) the class to associate with the specified column name, e.g. class.{RULE_ID} = scc_class'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite     = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n    text1 = '  validate-controls    = '\n    text2 = '(optional) on, warn, or off [default]; validate controls exist in resolved profile.'\n    logger.info(text1 + text2)\n    # Notes\n    text1 = ''\n    text2 = ''\n    logger.info(text1 + text2)\n    text1 = 'Notes: '\n    text2 = '[1] column is ignored for validation component type'\n    logger.info(text1 + text2)\n    text1 = '       '\n    text2 = '[2] column is required for validation component type'\n    logger.info(text1 + text2)\n    text1 = '       '\n    text2 = '[3] column name starting with # causes column to be ignored'\n    logger.info(text1 + text2)\n    text1 = '       '\n    text2 = '[4] additional parameters are specified by adding a common suffix per set'\n    text3 = f', for example: {PARAMETER_ID}_1, {PARAMETER_DESCRIPTION}_1, ...{PARAMETER_ID}_2...'\n    logger.info(text1 + text2 + text3)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.rules_add","title":"rules_add(self, add_rules)","text":"

                                    Add rules.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def rules_add(self, add_rules: List[str]) -> None:\n\"\"\"Add rules.\"\"\"\n    for rule_key in add_rules:\n        component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n        component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n        component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n        # component\n        component = self._cd_mgr.get_component(component_title, component_type, component_description)\n        # props\n        component.props = as_list(component.props)\n        component.props = component.props + self._create_rule_props(rule_key)\n        # additional props, when not validation component\n        if not self._is_validation(rule_key):\n            # control implementation\n            source = self._csv_mgr.get_value(rule_key, PROFILE_SOURCE)\n            description = self._csv_mgr.get_value(rule_key, PROFILE_DESCRIPTION)\n            control_implementation = self._get_control_implementation(component, source, description)\n            # set-parameters\n            set_parameters = self._create_set_parameters(rule_key)\n            if set_parameters:\n                control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n                _OscalHelper.add_set_parameters(control_implementation.set_parameters, set_parameters)\n            # control-mappings\n            control_mappings = self._csv_mgr.get_value(rule_key, CONTROL_ID_LIST).split()\n            self._add_rule_prop(control_implementation, control_mappings, rule_key)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.rules_del","title":"rules_del(self, del_rules)","text":"

                                    Delete rules.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def rules_del(self, del_rules: List[str]) -> None:\n\"\"\"Delete rules.\"\"\"\n    for tokens in del_rules:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        description = ''\n        # component\n        component = self._cd_mgr.get_component(component_title, component_type, description)\n        # props\n        component.props = self._delete_rule_props(component, rule_id)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.rules_mod","title":"rules_mod(self, mod_rules)","text":"

                                    Modify rules.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def rules_mod(self, mod_rules: List[str]) -> None:\n\"\"\"Modify rules.\"\"\"\n    for rule_key in mod_rules:\n        component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n        component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n        component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n        # component\n        component = self._cd_mgr.get_component(component_title, component_type, component_description)\n        # props\n        component.props = self._modify_rule_props(component, rule_key)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.set_params_add","title":"set_params_add(self, add_set_params)","text":"

                                    Set parameters add.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def set_params_add(self, add_set_params: List[str]) -> None:\n\"\"\"Set parameters add.\"\"\"\n    for tokens in add_set_params:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        param_id = tokens[5]\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n        # add\n        rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n        values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n        set_parameter = SetParameter(\n            param_id=param_id,\n            values=values,\n        )\n        _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.set_params_del","title":"set_params_del(self, del_set_params)","text":"

                                    Set parameters delete.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def set_params_del(self, del_set_params: List[str]) -> None:\n\"\"\"Set parameters delete.\"\"\"\n    for tokens in del_set_params:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        source = tokens[3]\n        description = tokens[4]\n        param_id = tokens[5]\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        if control_implementation:\n            set_parameters = control_implementation.set_parameters\n            control_implementation.set_parameters = []\n            for set_parameter in self._set_parameter_generator(set_parameters):\n                if set_parameter.param_id == param_id:\n                    continue\n                _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n            if control_implementation.set_parameters == []:\n                control_implementation.set_parameters = None\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.set_params_mod","title":"set_params_mod(self, mod_set_params)","text":"

                                    Set parameters modify.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def set_params_mod(self, mod_set_params: List[str]) -> None:\n\"\"\"Set parameters modify.\"\"\"\n    for tokens in mod_set_params:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        param_id = tokens[5]\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        if control_implementation:\n            set_parameters = control_implementation.set_parameters\n            for set_parameter in self._set_parameter_generator(set_parameters):\n                if set_parameter.param_id != param_id:\n                    continue\n                rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n                values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n                replacement = SetParameter(\n                    param_id=param_id,\n                    values=values,\n                )\n                if set_parameter.values == replacement.values:\n                    continue\n                logger.debug(f'params-mod: {rule_id} {param_id} {set_parameter.values} -> {replacement.values}')\n                set_parameter.values = replacement.values\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd-functions","title":"Functions","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.derive_control_id","title":"derive_control_id(control_mapping)","text":"

                                    Derive control id.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def derive_control_id(control_mapping: str) -> str:\n\"\"\"Derive control id.\"\"\"\n    rval = control_mapping.split('_smt')[0]\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.derive_part_id","title":"derive_part_id(control_mapping)","text":"

                                    Derive part id.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def derive_part_id(control_mapping: str) -> str:\n\"\"\"Derive part id.\"\"\"\n    if '_smt.' in control_mapping:\n        rval = control_mapping\n    else:\n        rval = None\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.etype","title":"etype(target)","text":"

                                    Get etype.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def etype(target: str) -> str:\n\"\"\"Get etype.\"\"\"\n    if target:\n        return 'invalid'\n    else:\n        return 'missing'\n
                                    "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.row_property_builder","title":"row_property_builder(row, name, value, ns, class_, remarks)","text":"

                                    Row property builder.

                                    Source code in trestle/tasks/csv_to_oscal_cd.py
                                    def row_property_builder(row: int, name: str, value, ns: str, class_: str, remarks: str) -> Property:\n\"\"\"Row property builder.\"\"\"\n    # name\n    try:\n        Property(\n            name=name,\n            value='value',\n        )\n    except Exception:\n        text = f'property for row: {row} name: {name} is {etype(name)}'\n        raise RuntimeError(text)\n    # value\n    try:\n        Property(\n            name=name,\n            value=value,\n        )\n    except Exception:\n        text = f'property for row: {row} value: {value} is {etype(value)}'\n        raise RuntimeError(text)\n    # ns\n    try:\n        Property(\n            name=name,\n            value=value,\n            ns=ns,\n        )\n    except Exception:\n        text = f'property for row: {row} ns: {ns} is {etype(ns)}'\n        raise RuntimeError(text)\n    # class\n    try:\n        Property(\n            name=name,\n            value=value,\n            class_=class_,\n        )\n    except Exception:\n        text = f'property for row: {row} class: {class_} is {etype(class_)}'\n        raise RuntimeError(text)\n    # prop\n    prop = Property(\n        name=name,\n        value=value,\n        ns=ns,\n        class_=class_,\n        remarks=remarks,\n    )\n    return prop\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/","title":"ocp4_cis_profile_to_oscal_catalog","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog","title":"trestle.tasks.ocp4_cis_profile_to_oscal_catalog","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node","title":" Node (BaseModel) pydantic-model","text":"

                                    Representation of CIS profile entry.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                    class Node(BaseModel):\n\"\"\"Representation of CIS profile entry.\"\"\"\n\n    name: Optional[str] = Field(None)\n    description: Optional[str] = Field(None)\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.description","title":"description: str pydantic-field","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.name","title":"name: str pydantic-field","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog","title":" Ocp4CisProfileToOscalCatalog (TaskBase) ","text":"

                                    Task to transform OCP4 CIS profile to OSCAL catalog.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                    class Ocp4CisProfileToOscalCatalog(TaskBase):\n\"\"\"\n    Task to transform OCP4 CIS profile to OSCAL catalog.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'ocp4-cis-profile-to-oscal-catalog'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task ocp4-cis-profile-to-oscal-catalog.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-catalog]:')\n        text1 = '  input-dir              = '\n        text2 = '(required) location to read the compliance-as-code profile files.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = '(required) location to write the generated catalog.json file.'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite       = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Wrap the execute for exception handling.\"\"\"\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        try:\n            idir = self._config['input-dir']\n            odir = self._config['output-dir']\n        except KeyError as e:\n            logger.info(f'key {e.args[0]} missing')\n            return TaskOutcome('failure')\n        # verbosity\n        quiet = self._config.get('quiet', False)\n        verbose = not quiet\n        # output\n        overwrite = self._config.getboolean('output-overwrite', True)\n        opth = pathlib.Path(odir)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'catalog.json'\n        ofile = opth / oname\n        if not overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # metadata links (optional)\n        metadata_links = self._config.get('metadata-links')\n        # get list or <name>.profile files\n        filelist = self._get_filelist(idir)\n        if len(filelist) < 1:\n            logger.warning(f'input: {idir} no .profile file found')\n            return TaskOutcome('failure')\n        # initialize node list\n        self._node_map = {}\n        # process files\n        for fp in filelist:\n            lines = self._get_content(fp)\n            self._parse(lines)\n        # get root nodes\n        root_nodes = self._get_root_nodes()\n        # groups and controls\n        root = Group(title='root', groups=[])\n        for node in root_nodes:\n            group = Group(title=f'{node.name} {node.description}')\n            root.groups.append(group)\n            depth = self._depth(node.name)\n            if depth == 3:\n                self._add_groups(group, node.name, depth)\n            if depth == 2:\n                self._add_controls(group, node.name, depth)\n        # metadata\n        metadata = Metadata(\n            title=self._title, last_modified=self._timestamp, oscal_version=OSCAL_VERSION, version=trestle.__version__\n        )\n        # metadata links\n        if metadata_links is not None:\n            metadata.links = []\n            for item in metadata_links.split():\n                link = Link(href=item)\n                metadata.links.append(link)\n        # catalog\n        catalog = Catalog(uuid=_uuid(), metadata=metadata, groups=root.groups)\n        # write OSCAL ComponentDefinition to file\n        if verbose:\n            logger.info(f'output: {ofile}')\n        catalog.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _get_filelist(self, idir: str) -> List[pathlib.Path]:\n\"\"\"Get filelist.\"\"\"\n        return [x for x in pathlib.Path(idir).iterdir() if x.is_file() and x.suffix == '.profile']\n\n    def _get_content(self, fp: pathlib.Path) -> List[str]:\n\"\"\"Fetch content from file.\"\"\"\n        content = None\n        try:\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            content = f.readlines()\n            f.close()\n            return content\n        except Exception as e:\n            logger.warning(f'unable to process {fp.name}')\n            raise e\n\n    def _parse(self, lines: List[str]) -> None:\n\"\"\"Parse lines to build data structure.\"\"\"\n        for line in lines:\n            line = line.strip()\n            if line.startswith('title: ') and \"'\" in line:\n                self._title = line.split(\"'\")[1]\n                continue\n            line_parts = line.split(None, 2)\n            # must be 3 parts exactly\n            if len(line_parts) < 3:\n                continue\n            # normalized name and description\n            name = line_parts[1].rstrip('.')\n            description = line_parts[2]\n            # name must be numbers and decimal points\n            if not set(name) <= set('0123456789.'):\n                continue\n            # derive desired sortable key from name\n            key = self._get_key(name)\n            self._node_map[key] = Node(name=name, description=description)\n\n    def _get_key(self, name: str) -> Tuple[int, int, int]:\n\"\"\"Convert name to desired sortable key.\"\"\"\n        parts = name.split('.')\n        if len(parts) == 1:\n            key = (int(parts[0]), 0, 0)\n        elif len(parts) == 2:\n            key = (int(parts[0]), int(parts[1]), 0)\n        elif len(parts) == 3:\n            key = (int(parts[0]), int(parts[1]), int(parts[2]))\n        else:\n            text = f'Unexpected value: {name}'\n            raise RuntimeError(text)\n        return key\n\n    def _get_root_nodes(self) -> ValuesView[Node]:\n\"\"\"Get root nodes.\"\"\"\n        root_nodes = {}\n        for node in self._node_map.values():\n            if len(node.name) == 1:\n                root_nodes[node.name] = node\n        return root_nodes.values()\n\n    def _depth(self, prefix: str) -> int:\n\"\"\"Get maximum depth for prefix.\"\"\"\n        depth = 0\n        for node in self._node_map.values():\n            name = node.name\n            if not name.startswith(prefix):\n                continue\n            dots = name.split('.')\n            if len(dots) <= depth:\n                continue\n            depth = len(dots)\n        return depth\n\n    def _add_controls(self, group: Group, prefix: str, depth: int):\n\"\"\"Add controls to group.\"\"\"\n        controls = []\n        for key in sorted(self._node_map.keys()):\n            node = self._node_map[key]\n            name = node.name\n            if name.startswith(prefix):\n                dots = name.split('.')\n                if len(dots) == depth:\n                    id_ = f'CIS-{node.name}'\n                    title = f'{node.name} {node.description}'\n                    control = Control(id=id_, title=title)\n                    controls.append(control)\n        if len(controls) > 0:\n            group.controls = controls\n\n    def _add_groups(self, group: Group, prefix: str, depth: int):\n\"\"\"Add sub-groups to group.\"\"\"\n        groups = []\n        for key in sorted(self._node_map.keys()):\n            node = self._node_map[key]\n            name = node.name\n            if not name.startswith(prefix):\n                continue\n            if name == prefix:\n                continue\n            dots = name.split('.')\n            if len(dots) != depth - 1:\n                continue\n            title = f'{node.name} {node.description}'\n            sub_group = Group(title=title)\n            groups.append(sub_group)\n            sub_prefix = node.name\n            self._add_controls(sub_group, sub_prefix, depth)\n        if len(groups) > 0:\n            group.groups = groups\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task ocp4-cis-profile-to-oscal-catalog.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task ocp4-cis-profile-to-oscal-catalog.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-catalog]:')\n    text1 = '  input-dir              = '\n    text2 = '(required) location to read the compliance-as-code profile files.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = '(required) location to write the generated catalog.json file.'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite       = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/","title":"ocp4_cis_profile_to_oscal_cd","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd","title":"trestle.tasks.ocp4_cis_profile_to_oscal_cd","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD","title":" Ocp4CisProfileToOscalCD (TaskBase) ","text":"

                                    Task to transform OCP4 CIS profile to OSCAL component-definition.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                    class Ocp4CisProfileToOscalCD(TaskBase):\n\"\"\"\n    Task to transform OCP4 CIS profile to OSCAL component-definition.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'ocp4-cis-profile-to-oscal-cd'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task ocp4-cis-profile-to-oscal-cd.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n        self._timestamp = timestamp\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create component definition from standard (e.g. CIS benchmark).')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-cd]:')\n        text1 = '  component-name         = '\n        text2 = 'component name, e.g. OSCO.'\n        logger.info(text1 + text2)\n        text1 = '  org-name               = '\n        text2 = 'organization name, e.g. International Business Machines.'\n        logger.info(text1 + text2)\n        text1 = '  org-remarks            = '\n        text2 = 'organization remarks, e.g. IBM.'\n        logger.info(text1 + text2)\n        text1 = '  folder-cac             = '\n        text2 = 'folder containing compliance-as-code artifacts, e.g adjunct-data/cis-benchmarks/content.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = 'location to write the generated component-definition.json file.'\n        logger.info(text1 + text2)\n        #\n        text1 = '  profile-name           = '\n        text2 = 'profile name, e.g. OCP4 CIS-benchmark v4.'\n        logger.info(text1 + text2)\n        text1 = '  profile-mnemonic       = '\n        text2 = 'profile mnemonic, e.g. ocp4-cis-node.'\n        logger.info(text1 + text2)\n        text1 = '  profile-ns             = '\n        text2 = 'profile ns, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud.'\n        logger.info(text1 + text2)\n        text1 = '  profile-version        = '\n        text2 = 'profile version, e.g. 1.1.'\n        logger.info(text1 + text2)\n        text1 = '  profile-check-version  = '\n        text2 = 'profile check version, e.g. 0.1.58.'\n        logger.info(text1 + text2)\n        #\n        text1 = '  profile-type           = '\n        text2 = 'profile type, e.g. OCP4.'\n        logger.info(text1 + text2)\n        text1 = '  profile-list           = '\n        text2 = 'profile list is blank separated list of \"<suffix>\" for config entries: '\n        logger.info(text1 + text2)\n        text1 = '                           profile-file.<suffix>, profile-title.<suffix>, profile-url.<suffix>'\n        text2 = ', e.g. cis cis-node.'\n        logger.info(text1 + text2)\n        text1 = '  profile-file.<suffix>  = '\n        text2 = 'path of the profile file to ingest'\n        text3 = ', e.g. ${folder-cac}/products/ocp4/profiles/cis-node.profile.'  # noqa\n        logger.info(text1 + text2 + text3)\n        text1 = '  profile-title.<suffix> = '\n        text2 = 'title of the profile'\n        text3 = ', e.g. CIS Red Hat OpenShift Container Platform 4 Benchmark.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  profile-url.<suffix>   = '\n        text2 = 'URL of the profile'\n        text3 = ', e.g. https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  rule-to-parameters-map = '\n        text2 = 'map file for set-parameters, e.g. '\n        text3 = 'adjunct-data/task-files/rule2var.json.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  selected-rules         = '\n        text2 = 'file with list of selected rules, e.g. '\n        text3 = 'adjunct-data/task-files/selected_rules.json.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  enabled-rules          = '\n        text2 = 'file with list of enabled rules, e.g. '\n        text3 = 'adjunct-data/task-files/enabled_rules.json.'\n        logger.info(text1 + text2 + text3)\n        #\n        text = ''\n        logger.info(text)\n        text = 'Notes:'\n        logger.info(text)\n        text = '1. If a control has selected rules but no enabled rules, then all those selected are included.'\n        logger.info(text)\n        text = '2. If a control has selected and enabled rules, then only those enabled are included.'\n        logger.info(text)\n        text = '3. If a control has no selected rules, then none are included regardless of enabled.'\n        logger.info(text)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        try:\n            component_name = self._config['component-name']\n            org_name = self._config['org-name']\n            org_remarks = self._config['org-remarks']\n            self._folder_cac = self._config['folder-cac']\n            profile_check_version = self._config['profile-check-version']\n            profile_type = self._config['profile-type']\n            profile_mnemonic = self._config['profile-mnemonic']\n            profile_name = self._config['profile-name']\n            profile_ns = self._config['profile-ns']\n            profile_version = self._config['profile-version']\n            profile_sets = {}\n            profile_list = self._config['profile-list'].split()\n            for profile in profile_list:\n                profile_sets[profile] = {}\n                profile_sets[profile]['profile-file'] = self._config[f'profile-file.{profile}']\n                profile_sets[profile]['profile-url'] = self._config[f'profile-url.{profile}']\n                profile_sets[profile]['profile-title'] = self._config[f'profile-title.{profile}']\n                profile_sets[profile]['profile-ns'] = profile_ns\n                profile_sets[profile]['component-name'] = component_name\n            odir = self._config['output-dir']\n        except KeyError as e:\n            logger.info(f'key {e.args[0]} missing')\n            return TaskOutcome('failure')\n        # selected rules\n        self._selected_rules = self._get_filter_rules('selected-rules', 'selected')\n        # enabled rules\n        self._enabled_rules = self._get_filter_rules('enabled-rules', 'enabled')\n        # verbosity\n        quiet = self._config.get('quiet', False)\n        verbose = not quiet\n        # output\n        overwrite = self._config.getboolean('output-overwrite', True)\n        opth = pathlib.Path(odir)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'component-definition.json'\n        ofile = opth / oname\n        if not overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # fetch rule to parameters map\n        self._rule_to_parm_map = self._get_parameters_map('rule-to-parameters-map')\n        # roles, responsible_roles, parties, responsible parties\n        party_uuid_01 = str(uuid.uuid4())\n        party_uuid_02 = str(uuid.uuid4())\n        party_uuid_03 = str(uuid.uuid4())\n        roles = self._build_roles()\n        responsible_roles = self._build_responsible_roles(party_uuid_01, party_uuid_02, party_uuid_03)\n        parties = self._build_parties(org_name, org_remarks, party_uuid_01, party_uuid_02, party_uuid_03)\n        responsible_parties = self._build_responsible_parties(party_uuid_01, party_uuid_02, party_uuid_03)\n        # metadata\n        metadata = Metadata(\n            title=f'Component definition for {profile_type} profiles',\n            last_modified=self._timestamp,\n            oscal_version=OSCAL_VERSION,\n            version=trestle.__version__,\n            roles=roles,\n            parties=parties,\n            responsible_parties=responsible_parties\n        )\n        # defined component\n        component_title = component_name\n        component_description = component_name\n        defined_component = DefinedComponent(\n            uuid=str(uuid.uuid4()),\n            description=component_description,\n            title=component_title,\n            type='Service',\n        )\n        # add control implementation per profile\n        prop1 = Property(\n            name='profile_name',\n            value=profile_name,\n            class_='scc_profile_name',\n            ns=profile_ns,\n        )\n        prop2 = Property(\n            name='profile_mnemonic',\n            value=profile_mnemonic,\n            class_='scc_profile_mnemonic',\n            ns=profile_ns,\n        )\n        prop3 = Property(\n            name='profile_version',\n            value=profile_version,\n            class_='scc_profile_version',\n            ns=profile_ns,\n        )\n        prop4 = Property(\n            name='profile_check_version',\n            value=profile_check_version,\n        )\n        props = [prop1, prop2, prop3, prop4]\n        for profile in profile_list:\n            profile_set = profile_sets[profile]\n            control_implementation = self._build_control_implementation(profile_set, responsible_roles, props)\n            if control_implementation is not None:\n                if defined_component.control_implementations is None:\n                    defined_component.control_implementations = [control_implementation]\n                else:\n                    defined_component.control_implementations.append(control_implementation)\n        # defined components\n        defined_components = [defined_component]\n        # component definition\n        component_definition = ComponentDefinition(\n            uuid=str(uuid.uuid4()),\n            metadata=metadata,\n            components=defined_components,\n        )\n        # write OSCAL ComponentDefinition to file\n        if verbose:\n            logger.info(f'output: {ofile}')\n        component_definition.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _get_set_parameter(self, rule: str) -> SetParameter:\n\"\"\"Get set parameter.\"\"\"\n        set_parameter = None\n        for key in self._rule_to_parm_map.keys():\n            logger.debug(f'{key} {rule}')\n            if key == rule:\n                value = self._rule_to_parm_map[key]\n                remarks = value['description']\n                options = value['options']\n                default_value = options['default']\n                logger.debug(f'key: {key} options: {options}')\n                set_parameter = SetParameter(\n                    param_id=rule,\n                    values=[f'{default_value}'],\n                    remarks=remarks,\n                )\n        return set_parameter\n\n    def _get_controls(self, rules: Dict[str, Tuple[str, str, str]]) -> Dict[str, List[str]]:\n\"\"\"Get controls.\"\"\"\n        controls = {}\n        for rule in rules.keys():\n            control = rules[rule][1]\n            if control not in controls.keys():\n                controls[control] = [rule]\n            else:\n                controls[control] = controls[control] + [rule]\n        # trim rules associated with control with respect to enabled rules\n        for control in controls:\n            controls[control] = self._get_trimmed_rules(control, controls[control])\n            logger.debug(f'{control} {controls[control]}')\n        return controls\n\n    # determine if trim is needed for the control, and if so then\n    # for the associated set of rules drop those that are not enabled\n    def _get_trimmed_rules(self, control: str, rules_for_control: List[str]) -> List[str]:\n\"\"\"Trim rules if any rule for control appears in enabled rules list.\"\"\"\n        retval = rules_for_control\n        if self._is_trim_needed(rules_for_control):\n            retval = []\n            for rule in rules_for_control:\n                if rule in self._enabled_rules:\n                    retval = retval + [rule]\n                    logger.debug(f'keep {control} {rule}')\n                else:\n                    logger.debug(f'drop {control} {rule}')\n        return retval\n\n    # if any rule in the set of rules for the control appears in the enabled list,\n    # then trim is needed\n    def _is_trim_needed(self, rules_for_control: List[str]) -> bool:\n\"\"\"Check if trim is needed.\"\"\"\n        retval = False\n        for rule in rules_for_control:\n            if rule in self._enabled_rules:\n                retval = True\n                break\n        return retval\n\n    # fetch the set of rules that will be included/excluded from the CIS rules\n    def _get_parameters_map(self, config_key: str) -> List[str]:\n\"\"\"Get parameters map.\"\"\"\n        try:\n            fp = pathlib.Path(self._config[config_key])\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            jdata = json.load(f)\n            parameters_map = jdata\n            f.close()\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            parameters_map = {}\n        except Exception:\n            logger.warning(f'unable to process {self._config[config_key]}')\n            parameters_map = {}\n        return parameters_map\n\n    # fetch the set of rules that will be included/excluded from the CIS rules\n    def _get_filter_rules(self, config_key: str, file_key: str) -> List[str]:\n\"\"\"Get filter rules.\"\"\"\n        try:\n            fp = pathlib.Path(self._config[config_key])\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            jdata = json.load(f)\n            try:\n                filter_rules = jdata[file_key]\n            except Exception:\n                filter_rules = jdata\n            f.close()\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            filter_rules = []\n        except Exception:\n            logger.warning(f'unable to process {self._config[config_key]}')\n            filter_rules = []\n        return filter_rules\n\n    # create map from file:\n    # key is rule\n    # value is tuple comprising [ category, control, description ]\n    def _get_cis_rules(self, filename: str) -> Dict[str, Tuple[str, str, str]]:\n\"\"\"Get CIS rules.\"\"\"\n        try:\n            fp = pathlib.Path(filename)\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            content = f.readlines()\n            rules = self._parse_cis_rules(content)\n            f.close()\n        except Exception:\n            logger.warning(f'unable to process {filename}')\n            rules = {}\n        return rules\n\n    def _parse_cis_rules(self, content: List[str]) -> Dict[str, Tuple[str, str, str]]:\n\"\"\"Parse CIS rules.\"\"\"\n        rules = {}\n        lineno = 0\n        for line in content:\n            lineno += 1\n            line = line.replace('\\n', '')\n            if line.startswith('  #### '):\n                category = line.split('  #### ')[1]\n                logger.debug(f'{lineno} category: {category}')\n            elif line.startswith('  # '):\n                text = line.split('  # ')[1].split(' ', 1)\n                if '.' in text[0]:\n                    control = text[0]\n                    desc = text[1]\n                    logger.debug(f'{lineno} control: {control} description: {desc}')\n                else:\n                    logger.debug(f'{lineno} skip: {line}')\n            elif line.startswith('    - '):\n                rule = line.split('    - ')[1]\n                logger.debug(f'{lineno} rule: {rule}')\n                if not self._is_selected(rule):\n                    logger.debug(f'not selected rule: {rule}')\n                elif rule in rules.keys():\n                    logger.info(f'duplicate rule: {rule}')\n                else:\n                    rules[rule] = [category, control, desc]\n            else:\n                logger.debug(f'{lineno} skip: {line}')\n        return rules\n\n    # rule is selected if:\n    # a) the selected rules file is not specified or is empty or\n    # b) the rule appears in the list of selected rules from the file\n    def _is_selected(self, rule: str) -> bool:\n\"\"\"Check if rule is selected.\"\"\"\n        retval = True\n        if len(self._selected_rules) > 0 and rule not in self._selected_rules:\n            retval = False\n        logger.debug(f'{retval} {rule}')\n        return retval\n\n    # rule is excluded if it does not appear in the list of trimmed rules\n    # for the control\n    def _is_excluded(self, rule: str, control: str, controls: Dict[str, List[str]]) -> bool:\n\"\"\"Check if rule is excluded.\"\"\"\n        retval = False\n        if rule not in controls[control]:\n            logger.debug(f'exclude {rule} {control}')\n            retval = True\n        return retval\n\n    def _build_roles(self) -> List[Role]:\n\"\"\"Build roles.\"\"\"\n        value = [\n            Role(id='prepared-by', title='Indicates the organization that created this content.'),\n            Role(id='prepared-for', title='Indicates the organization for which this content was created..'),\n            Role(\n                id='content-approver',\n                title='Indicates the organization responsible for all content represented in the \"document\".'\n            ),\n        ]\n        return value\n\n    def _build_control_implementation(\n        self, profile_set: Dict[str, str], responsible_roles: List[ResponsibleRole], props: List[Property]\n    ) -> ControlImplementation:\n\"\"\"Build control implementation.\"\"\"\n        implemented_requirements = self._build_implemented_requirements(profile_set, responsible_roles)\n        if len(implemented_requirements) == 0:\n            control_implementation = None\n        else:\n            control_implementation = ControlImplementation(\n                uuid=str(uuid.uuid4()),\n                source=profile_set['profile-url'],\n                description=f'{profile_set[\"component-name\"]} implemented controls for {profile_set[\"profile-title\"]}.',\n                implemented_requirements=implemented_requirements,\n                props=props,\n            )\n        return control_implementation\n\n    def _get_title(self, dir_name: str, root: str) -> str:\n\"\"\"Extract rule title from compliance-as-code rule.yml.\"\"\"\n\"\"\"\n        Operation:\n        Given is a dir_name and a root directory. We walk the\n        directory tree looking for a directory named dir_name.\n        Once found, we read the content of the rule.yml file in\n        that directory. It is likely that we read each rule.yml\n        file exactly once, since each rule appears exactly once\n        in the one or more profiles, e.g. cis-node.profile, which\n        drive the search. From the content, we find the title and\n        return its corresponding value.\n        \"\"\"\n\n        title = None\n        for path, dirs, _files in os.walk(root):\n            if dir_name in dirs:\n                folder = os.path.join(path, dir_name)\n                tpath = pathlib.Path(folder) / 'rule.yml'\n                fp = pathlib.Path(tpath)\n                f = fp.open('r', encoding=const.FILE_ENCODING)\n                content = f.readlines()\n                f.close()\n                for line in content:\n                    if line.startswith('title:'):\n                        title = line.split('title:')[1]\n                        break\n        if title is None:\n            msg = f'unable to find \"{dir_name}\"'\n            logger.warning(msg)\n            title = 'no title'\n        title = title.strip().strip(\"'\").strip('\"')\n        logger.debug(f'{title}')\n        return title\n\n    def _build_implemented_requirements(self, profile_set: Dict[str, str],\n                                        responsible_roles: List[ResponsibleRole]) -> List[ImplementedRequirement]:\n\"\"\"Build implemented requirements.\"\"\"\n        implemented_requirements = []\n        profile_file = profile_set['profile-file']\n        rules = self._get_cis_rules(profile_file)\n        controls = self._get_controls(rules)\n        rule_prefix = 'xccdf_org.ssgproject.content_rule_'\n        cac_openshift = f'{self._folder_cac}/applications/openshift'\n        for rule in rules:\n            if self._is_excluded(rule, rules[rule][1], controls):\n                continue\n            remarks = self._get_title(rule, cac_openshift)\n            prop = Property(\n                class_='scc_goal_name_id',\n                ns=profile_set['profile-ns'],\n                name='XCCDF_rule',\n                value=f'{rule_prefix}{rule}',\n                remarks=f'{remarks}'\n            )\n            props = [prop]\n            implemented_requirement = ImplementedRequirement(\n                uuid=f'{str(uuid.uuid4())}',\n                control_id=f'CIS-{rules[rule][1]}',\n                description=f'{rules[rule][2]}',\n                props=props,\n                responsible_roles=responsible_roles,\n            )\n            set_parameter = self._get_set_parameter(rule)\n            if set_parameter is not None:\n                implemented_requirement.set_parameters = [set_parameter]\n            implemented_requirements.append(implemented_requirement)\n        return implemented_requirements\n\n    def _build_responsible_roles(self, party_uuid_01: str, party_uuid_02: str,\n                                 party_uuid_03: str) -> List[ResponsibleRole]:\n\"\"\"Build responsible roles.\"\"\"\n        role_prepared_by = ResponsibleRole(role_id='prepared-by', party_uuids=[party_uuid_01])\n        role_prepared_for = ResponsibleRole(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        role_content_approver = ResponsibleRole(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            role_prepared_by,\n            role_prepared_for,\n            role_content_approver,\n        ]\n        return value\n\n    def _build_parties(\n        self, org_name: str, org_remarks: str, party_uuid_01: str, party_uuid_02: str, party_uuid_03: str\n    ) -> List[Party]:\n\"\"\"Build parties.\"\"\"\n        value = [\n            Party(uuid=party_uuid_01, type='organization', name=org_name, remarks=org_remarks),\n            Party(\n                uuid=party_uuid_02,\n                type='organization',\n                name='Customer',\n                remarks='organization to be customized at account creation only for their Component Definition'\n            ),\n            Party(\n                uuid=party_uuid_03,\n                type='organization',\n                name='ISV',\n                remarks='organization to be customized at ISV subscription only for their Component Definition'\n            ),\n        ]\n        return value\n\n    def _build_responsible_parties(self, party_uuid_01: str, party_uuid_02: str,\n                                   party_uuid_03: str) -> List[ResponsibleParty]:\n\"\"\"Build responsible parties.\"\"\"\n        prepared_by = ResponsibleParty(role_id='prepared-by', party_uuids=[party_uuid_01])\n        prepared_for = ResponsibleParty(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        content_approver = ResponsibleParty(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            prepared_by,\n            prepared_for,\n            content_approver,\n        ]\n        return value\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task ocp4-cis-profile-to-oscal-cd.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task ocp4-cis-profile-to-oscal-cd.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create component definition from standard (e.g. CIS benchmark).')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-cd]:')\n    text1 = '  component-name         = '\n    text2 = 'component name, e.g. OSCO.'\n    logger.info(text1 + text2)\n    text1 = '  org-name               = '\n    text2 = 'organization name, e.g. International Business Machines.'\n    logger.info(text1 + text2)\n    text1 = '  org-remarks            = '\n    text2 = 'organization remarks, e.g. IBM.'\n    logger.info(text1 + text2)\n    text1 = '  folder-cac             = '\n    text2 = 'folder containing compliance-as-code artifacts, e.g adjunct-data/cis-benchmarks/content.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = 'location to write the generated component-definition.json file.'\n    logger.info(text1 + text2)\n    #\n    text1 = '  profile-name           = '\n    text2 = 'profile name, e.g. OCP4 CIS-benchmark v4.'\n    logger.info(text1 + text2)\n    text1 = '  profile-mnemonic       = '\n    text2 = 'profile mnemonic, e.g. ocp4-cis-node.'\n    logger.info(text1 + text2)\n    text1 = '  profile-ns             = '\n    text2 = 'profile ns, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud.'\n    logger.info(text1 + text2)\n    text1 = '  profile-version        = '\n    text2 = 'profile version, e.g. 1.1.'\n    logger.info(text1 + text2)\n    text1 = '  profile-check-version  = '\n    text2 = 'profile check version, e.g. 0.1.58.'\n    logger.info(text1 + text2)\n    #\n    text1 = '  profile-type           = '\n    text2 = 'profile type, e.g. OCP4.'\n    logger.info(text1 + text2)\n    text1 = '  profile-list           = '\n    text2 = 'profile list is blank separated list of \"<suffix>\" for config entries: '\n    logger.info(text1 + text2)\n    text1 = '                           profile-file.<suffix>, profile-title.<suffix>, profile-url.<suffix>'\n    text2 = ', e.g. cis cis-node.'\n    logger.info(text1 + text2)\n    text1 = '  profile-file.<suffix>  = '\n    text2 = 'path of the profile file to ingest'\n    text3 = ', e.g. ${folder-cac}/products/ocp4/profiles/cis-node.profile.'  # noqa\n    logger.info(text1 + text2 + text3)\n    text1 = '  profile-title.<suffix> = '\n    text2 = 'title of the profile'\n    text3 = ', e.g. CIS Red Hat OpenShift Container Platform 4 Benchmark.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  profile-url.<suffix>   = '\n    text2 = 'URL of the profile'\n    text3 = ', e.g. https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  rule-to-parameters-map = '\n    text2 = 'map file for set-parameters, e.g. '\n    text3 = 'adjunct-data/task-files/rule2var.json.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  selected-rules         = '\n    text2 = 'file with list of selected rules, e.g. '\n    text3 = 'adjunct-data/task-files/selected_rules.json.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  enabled-rules          = '\n    text2 = 'file with list of enabled rules, e.g. '\n    text3 = 'adjunct-data/task-files/enabled_rules.json.'\n    logger.info(text1 + text2 + text3)\n    #\n    text = ''\n    logger.info(text)\n    text = 'Notes:'\n    logger.info(text)\n    text = '1. If a control has selected rules but no enabled rules, then all those selected are included.'\n    logger.info(text)\n    text = '2. If a control has selected and enabled rules, then only those enabled are included.'\n    logger.info(text)\n    text = '3. If a control has no selected rules, then none are included regardless of enabled.'\n    logger.info(text)\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.set_timestamp","title":"set_timestamp(self, timestamp)","text":"

                                    Set the timestamp.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n    self._timestamp = timestamp\n
                                    "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/","title":"oscal_catalog_to_csv","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv","title":"trestle.tasks.oscal_catalog_to_csv","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_control","title":"level_control","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_default","title":"level_default","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_list","title":"level_list","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_statement","title":"level_statement","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.recurse","title":"recurse","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.timestamp","title":"timestamp","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper","title":" CatalogHelper ","text":"

                                    OSCAL Catalog Helper.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    class CatalogHelper:\n\"\"\"OSCAL Catalog Helper.\"\"\"\n\n    def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n        self.path = path\n        self.catalog = Catalog.oscal_read(path)\n        self.catalog_interface = CatalogInterface(self.catalog)\n        self._init_control_parent_map()\n\n    def _init_control_parent_map(self, recurse=True) -> None:\n\"\"\"Initialize map: Child Control.id to parent Control.\"\"\"\n        self._control_parent_map = {}\n        for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n            parents = self.catalog_interface.get_dependent_control_ids(control.id)\n            for parent in parents:\n                # assert child has only one parent\n                if parent in self._control_parent_map.keys():\n                    raise RuntimeError('{parent} duplicate?')\n                self._control_parent_map[parent] = control\n\n    def get_parent_control(self, ctl_id: str) -> Control:\n\"\"\"Return parent Control of child Control.id, if any.\"\"\"\n        return self._control_parent_map.get(ctl_id)\n\n    def get_family_controls(self, ctl_id: str) -> List[Control]:\n\"\"\"Return family of controls for Control.id, if any.\"\"\"\n        rval = []\n        search_id = ctl_id.split('.')[0]\n        for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n            if control.id.startswith(search_id):\n                rval.append(control)\n        return rval\n\n    def get_controls(self, recurse=True) -> Iterator:\n\"\"\"Return controls iterator.\"\"\"\n        for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n            yield control\n\n    def get_statement_text_for_control(self, control: Control) -> Optional[str]:\n\"\"\"Get statement text for control.\"\"\"\n        statement_text = self._withdrawn(control)\n        return statement_text\n\n    def get_statement_text_for_part(self, control: Control, part: Part) -> Optional[str]:\n\"\"\"Get statement text for part.\"\"\"\n        statement_text = self._derive_text(control, part)\n        if part.parts:\n            for subpart in part.parts:\n                if '_smt' in subpart.id:\n                    partial_text = self._derive_text(control, subpart)\n                    statement_text = join_str(statement_text, partial_text)\n        return statement_text\n\n    def _withdrawn(self, control: Control) -> Optional[str]:\n\"\"\"Check if withdrawn.\"\"\"\n        rval = None\n        for prop in control.props:\n            if prop.name.lower() == 'status' and prop.value.lower() == 'withdrawn':\n                status = self._get_status(control)\n                rval = join_str('Withdrawn', status, '')\n                rval = f'[{rval}]'\n                break\n        return rval\n\n    def _link_generator(self, control: Control) -> Iterator[Link]:\n\"\"\"Link generator.\"\"\"\n        if control.links:\n            for link in control.links:\n                yield link\n\n    def _get_status(self, control: Control) -> Optional[str]:\n\"\"\"Get status.\"\"\"\n        rval = None\n        ilist = None\n        for link in self._link_generator(control):\n            if link.rel.lower() == 'moved-to':\n                moved = self._href_to_control(link.href)\n                rval = f': Moved to {moved}.'\n                break\n            if link.rel.lower() == 'incorporated-into':\n                incorporated = self._href_to_control(link.href)\n                if ilist is None:\n                    ilist = f'{incorporated}'\n                else:\n                    ilist = f'{ilist}, {incorporated}'\n        if ilist:\n            rval = f': Incorporated into {ilist}.'\n        return rval\n\n    def _href_to_control(self, href: str) -> str:\n\"\"\"Convert href to control.\"\"\"\n        rval = href.replace('#', '').upper()\n        return rval\n\n    def _derive_text(self, control: Control, part: Part) -> Optional[str]:\n\"\"\"Derive control text.\"\"\"\n        rval = None\n        if part.prose:\n            id_ = self._derive_id(part.id)\n            text = self._resolve_parms(control, part.prose)\n            rval = join_str(id_, text)\n        return rval\n\n    def _derive_id(self, id_: str) -> str:\n\"\"\"Derive control text sub-part id.\"\"\"\n        rval = None\n        id_parts = id_.split('_smt')\n        if id_parts[1]:\n            id_sub_parts = id_parts[1].split('.')\n            if len(id_sub_parts) == 2:\n                rval = f'{id_sub_parts[1]}.'\n            elif len(id_sub_parts) == 3:\n                rval = f'{id_sub_parts[2]}.'\n            elif len(id_sub_parts) == 4:\n                rval = f'({id_sub_parts[3]})'\n        return rval\n\n    def _resolve_parms(self, control: Control, utext: str) -> str:\n\"\"\"Resolve parm.\"\"\"\n        rtext = self._resolve_parms_for_control(control, utext)\n        if '{{' in rtext:\n            parent_control = self.get_parent_control(control.id)\n            if parent_control:\n                rtext = self._resolve_parms_for_control(parent_control, rtext)\n        if '{{' in rtext:\n            family_controls = self.get_family_controls(control.id)\n            for family_control in family_controls:\n                rtext = self._resolve_parms_for_control(family_control, rtext)\n        if '{{' in rtext:\n            text = f'control.id: {control.id} unresolved: {rtext}'\n            raise RuntimeError(text)\n        return rtext\n\n    def _resolve_parms_for_control(self, control: Control, utext: str) -> str:\n\"\"\"Resolve parms for control.\"\"\"\n        rtext = utext\n        staches: List[str] = re.findall(r'{{.*?}}', utext)\n        if staches:\n            for stach in staches:\n                parm_id = stach\n                parm_id = parm_id.replace('{{', '')\n                parm_id = parm_id.replace('}}', '')\n                parm_id = parm_id.split(',')[1].strip()\n                value = self._get_parm_value(control, parm_id)\n                if value:\n                    rtext = rtext.replace(stach, value)\n        return rtext\n\n    def _get_parm_value(self, control: Control, parm_id: str) -> str:\n\"\"\"Get parm value.\"\"\"\n        rval = None\n        if control.params:\n            for param in control.params:\n                if param.id != parm_id:\n                    continue\n                if param.label:\n                    rval = f'[Assignment: {param.label}]'\n                elif param.select:\n                    choices = self._get_parm_choices(control, param)\n                    if param.select.how_many == HowMany.one:\n                        rval = f'[Selection (one): {choices}]'\n                    else:\n                        rval = f'[Selection (one or more): {choices}]'\n                    break\n        return rval\n\n    def _get_parm_choices(self, control: Control, param: Parameter) -> str:\n\"\"\"Get parm choices.\"\"\"\n        choices = ''\n        for choice in param.select.choice:\n            rchoice = self._resolve_parms(control, choice)\n            if choices:\n                choices += f'; {rchoice}'\n            else:\n                choices += f'{rchoice}'\n        return choices\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.__init__","title":"__init__(self, path) special","text":"

                                    Initialize.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n    self.path = path\n    self.catalog = Catalog.oscal_read(path)\n    self.catalog_interface = CatalogInterface(self.catalog)\n    self._init_control_parent_map()\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_controls","title":"get_controls(self, recurse=True)","text":"

                                    Return controls iterator.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def get_controls(self, recurse=True) -> Iterator:\n\"\"\"Return controls iterator.\"\"\"\n    for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n        yield control\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_family_controls","title":"get_family_controls(self, ctl_id)","text":"

                                    Return family of controls for Control.id, if any.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def get_family_controls(self, ctl_id: str) -> List[Control]:\n\"\"\"Return family of controls for Control.id, if any.\"\"\"\n    rval = []\n    search_id = ctl_id.split('.')[0]\n    for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n        if control.id.startswith(search_id):\n            rval.append(control)\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_parent_control","title":"get_parent_control(self, ctl_id)","text":"

                                    Return parent Control of child Control.id, if any.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def get_parent_control(self, ctl_id: str) -> Control:\n\"\"\"Return parent Control of child Control.id, if any.\"\"\"\n    return self._control_parent_map.get(ctl_id)\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_statement_text_for_control","title":"get_statement_text_for_control(self, control)","text":"

                                    Get statement text for control.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def get_statement_text_for_control(self, control: Control) -> Optional[str]:\n\"\"\"Get statement text for control.\"\"\"\n    statement_text = self._withdrawn(control)\n    return statement_text\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_statement_text_for_part","title":"get_statement_text_for_part(self, control, part)","text":"

                                    Get statement text for part.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def get_statement_text_for_part(self, control: Control, part: Part) -> Optional[str]:\n\"\"\"Get statement text for part.\"\"\"\n    statement_text = self._derive_text(control, part)\n    if part.parts:\n        for subpart in part.parts:\n            if '_smt' in subpart.id:\n                partial_text = self._derive_text(control, subpart)\n                statement_text = join_str(statement_text, partial_text)\n    return statement_text\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager","title":" ContentManager ","text":"

                                    Content manager.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    class ContentManager():\n\"\"\"Content manager.\"\"\"\n\n    def __init__(self, catalog_helper: CatalogHelper) -> None:\n\"\"\"Initialize.\"\"\"\n        self.catalog_helper = catalog_helper\n        self.rows = []\n        self.row_template = None\n\n    def add(self, row: List):\n\"\"\"Add row.\"\"\"\n        n_row = copy.copy(row)\n        t_row = self.row_template\n        if t_row:\n            for index in range(3):\n                if n_row[index] == t_row[index]:\n                    n_row[index] = None\n        self.rows.append(n_row)\n        self.row_template = row\n\n    def get_content(self, level: str) -> List:\n\"\"\"Get content.\"\"\"\n        if level == level_control:\n            rval = self._get_content_by_control()\n        else:\n            rval = self._get_content_by_statement()\n        return rval\n\n    def _get_content_by_statement(self) -> List:\n\"\"\"Get content by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        header = ['Control Identifier', 'Control Title', 'Statement Identifier', 'Statement Text']\n        self.rows.append(header)\n        for control in catalog_helper.get_controls():\n            control_id = convert_control_id(control.id)\n            if control.parts:\n                self._add_parts_by_statement(control)\n            else:\n                statement_text = catalog_helper.get_statement_text_for_control(control)\n                row = [control_id, control.title, '', statement_text]\n                self.add(row)\n        return self.rows\n\n    def _add_subparts_by_statement(self, control: Control, part: Part) -> None:\n\"\"\"Add subparts by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        control_id = convert_control_id(control.id)\n        for subpart in part.parts:\n            if '_smt' in subpart.id:\n                statement_text = catalog_helper.get_statement_text_for_part(control, subpart)\n                row = [control_id, control.title, convert_smt_id(subpart.id), statement_text]\n                self.add(row)\n\n    def _add_parts_by_statement(self, control: Control) -> None:\n\"\"\"Add parts by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        control_id = convert_control_id(control.id)\n        for part in control.parts:\n            if part.id:\n                if '_smt' not in part.id:\n                    continue\n                if part.parts:\n                    self._add_subparts_by_statement(control, part)\n                else:\n                    statement_text = catalog_helper.get_statement_text_for_part(control, part)\n                    row = [control_id, control.title, convert_smt_id(part.id), statement_text]\n                    self.add(row)\n\n    def _get_content_by_control(self) -> List:\n\"\"\"Get content by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        header = ['Control Identifier', 'Control Title', 'Control Text']\n        self.rows.append(header)\n        for control in catalog_helper.get_controls():\n            control_id = convert_control_id(control.id)\n            if control.parts:\n                self._add_parts_by_control(control)\n            else:\n                control_text = catalog_helper.get_statement_text_for_control(control)\n                row = [control_id, control.title, control_text]\n                self.add(row)\n        return self.rows\n\n    def _add_subparts_by_control(self, control: Control, part: Part, control_text) -> str:\n\"\"\"Add subparts by control.\"\"\"\n        catalog_helper = self.catalog_helper\n        for subpart in part.parts:\n            if '_smt' in subpart.id:\n                statement_text = catalog_helper.get_statement_text_for_part(control, subpart)\n                control_text = join_str(control_text, statement_text)\n        return control_text\n\n    def _add_parts_by_control(self, control: Control) -> None:\n\"\"\"Add parts by control.\"\"\"\n        catalog_helper = self.catalog_helper\n        control_id = convert_control_id(control.id)\n        control_text = None\n        for part in control.parts:\n            if part.id:\n                if '_smt' not in part.id:\n                    continue\n                if part.parts:\n                    control_text = self._add_subparts_by_control(control, part, control_text)\n                else:\n                    statement_text = catalog_helper.get_statement_text_for_part(control, part)\n                    control_text = join_str(control_text, statement_text)\n        row = [control_id, control.title, control_text]\n        self.add(row)\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager.__init__","title":"__init__(self, catalog_helper) special","text":"

                                    Initialize.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def __init__(self, catalog_helper: CatalogHelper) -> None:\n\"\"\"Initialize.\"\"\"\n    self.catalog_helper = catalog_helper\n    self.rows = []\n    self.row_template = None\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager.add","title":"add(self, row)","text":"

                                    Add row.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def add(self, row: List):\n\"\"\"Add row.\"\"\"\n    n_row = copy.copy(row)\n    t_row = self.row_template\n    if t_row:\n        for index in range(3):\n            if n_row[index] == t_row[index]:\n                n_row[index] = None\n    self.rows.append(n_row)\n    self.row_template = row\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager.get_content","title":"get_content(self, level)","text":"

                                    Get content.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def get_content(self, level: str) -> List:\n\"\"\"Get content.\"\"\"\n    if level == level_control:\n        rval = self._get_content_by_control()\n    else:\n        rval = self._get_content_by_statement()\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper","title":" CsvHelper ","text":"

                                    Csv Helper.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    class CsvHelper:\n\"\"\"Csv Helper.\"\"\"\n\n    def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n        self.path = path\n\n    def write(self, rows: List[List[str]]) -> None:\n\"\"\"Write csv file.\"\"\"\n        with open(self.path, 'w', newline='', encoding='utf-8') as output:\n            csv_writer = csv.writer(output, delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n            for row in rows:\n                csv_writer.writerow(row)\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper.__init__","title":"__init__(self, path) special","text":"

                                    Initialize.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n    self.path = path\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper.write","title":"write(self, rows)","text":"

                                    Write csv file.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def write(self, rows: List[List[str]]) -> None:\n\"\"\"Write csv file.\"\"\"\n    with open(self.path, 'w', newline='', encoding='utf-8') as output:\n        csv_writer = csv.writer(output, delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n        for row in rows:\n            csv_writer.writerow(row)\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv","title":" OscalCatalogToCsv (TaskBase) ","text":"

                                    Task to transform OSCAL catalog to .csv.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    class OscalCatalogToCsv(TaskBase):\n\"\"\"\n    Task to transform OSCAL catalog to .csv.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'oscal-catalog-to-csv'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create .csv from OSCAL catalog.')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.oscal-catalog-to-csv]:')\n        text1 = '  input-file             = '\n        text2 = '(required) path of file to read the catalog.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = '(required) path of directory to write the generated .csv file.'\n        logger.info(text1 + text2)\n        text1 = '  output-name            = '\n        text2 = '(optional) name of the generated .csv file [default is name of input file with .csv suffix].'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite       = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n        text1 = '  level                  = '\n        text2 = f'(optional) one of: {level_control} or {level_statement} [default].'\n        logger.info(text1 + text2)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Wrap the execute for exception handling.\"\"\"\n        # config processing\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        # input\n        ifile = self._config.get('input-file')\n        if not ifile:\n            logger.warning('input-file missing')\n            return TaskOutcome('failure')\n        ipth = pathlib.Path(ifile)\n        # overwrite\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # output\n        odir = self._config.get('output-dir')\n        if not odir:\n            logger.warning('output-dir missing')\n            return TaskOutcome('failure')\n        opth = pathlib.Path(odir)\n        opth.mkdir(exist_ok=True, parents=True)\n        iname = ipth.name.split('.')[0]\n        oname = self._config.get('output-name', f'{iname}.csv')\n        opth = opth / oname\n        if not self._overwrite and opth.exists():\n            logger.warning(f'output: {opth} already exists')\n            return TaskOutcome('failure')\n        csv_helper = CsvHelper(opth)\n        # level\n        level = self._config.get('level', level_default)\n        if level not in level_list:\n            logger.warning(f'level: {level} unknown')\n            return TaskOutcome('failure')\n        # helper\n        catalog_helper = CatalogHelper(ipth)\n        # process\n        content_manager = ContentManager(catalog_helper)\n        rows = content_manager.get_content(level)\n        # write\n        csv_helper.write(rows)\n        logger.info(f'output-file: {opth}')\n        # success\n        return TaskOutcome('success')\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create .csv from OSCAL catalog.')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.oscal-catalog-to-csv]:')\n    text1 = '  input-file             = '\n    text2 = '(required) path of file to read the catalog.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = '(required) path of directory to write the generated .csv file.'\n    logger.info(text1 + text2)\n    text1 = '  output-name            = '\n    text2 = '(optional) name of the generated .csv file [default is name of input file with .csv suffix].'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite       = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n    text1 = '  level                  = '\n    text2 = f'(optional) one of: {level_control} or {level_statement} [default].'\n    logger.info(text1 + text2)\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv-functions","title":"Functions","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.convert_control_id","title":"convert_control_id(control_id)","text":"

                                    Convert control id.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def convert_control_id(control_id: str) -> str:\n\"\"\"Convert control id.\"\"\"\n    rval = copy.copy(control_id)\n    rval = rval.upper()\n    if '.' in rval:\n        rval = rval.replace('.', '(')\n        rval = rval + ')'\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.convert_smt_id","title":"convert_smt_id(smt_id)","text":"

                                    Convert smt id.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def convert_smt_id(smt_id: str) -> str:\n\"\"\"Convert smt id.\"\"\"\n    parts = smt_id.split('_smt')\n    seg1 = convert_control_id(parts[0])\n    seg2 = ''\n    if len(parts) == 2:\n        seg2 = parts[1]\n        if '.' in seg2:\n            seg2 = seg2.replace('.', '(')\n            seg2 = seg2 + ')'\n    rval = f'{seg1}{seg2}'\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.join_str","title":"join_str(s1, s2, sep=' ')","text":"

                                    Join strings.

                                    Source code in trestle/tasks/oscal_catalog_to_csv.py
                                    def join_str(s1: Optional[str], s2: Optional[str], sep: str = ' ') -> Optional[str]:\n\"\"\"Join strings.\"\"\"\n    if s1 is None:\n        rval = s2\n    elif s2 is None:\n        rval = s1\n    else:\n        rval = f'{s1}{sep}{s2}'\n    return rval\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/","title":"oscal_profile_to_osco_profile","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile","title":"trestle.tasks.oscal_profile_to_osco_profile","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco","title":" ProfileToOsco (TaskBase) ","text":"

                                    Task to convert Profile to OSC yaml.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                    class ProfileToOsco(TaskBase):\n\"\"\"\n    Task to convert Profile to OSC yaml.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'oscal-profile-to-osco-profile'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task oscal-profile-to-osco-profile.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Open Security Controls Assessment Language (OSCAL) Profile '\n            + 'into Open Shift Compliance Operator (OSCO) .yaml file.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.oscal-profile-to-osco-profile]:')\n        logger.info('  input-file = (required) path of the input file comprising OSCAL profile.')\n        logger.info('  output-dir = (required) path of the output directory comprising synthesized .yaml file.')\n        logger.info(\n            '  output-name = (optional) name of created file in output directory, default is osco-profile.yaml.'\n        )\n        logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n        logger.info(\n            '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n        )\n        logger.info('')\n        logger.info('Operation: The specified input profile is transformed into OSCO .yaml.')\n        logger.info('')\n        logger.info('Notes:')\n        note11 = '[1] The input-file OSCAL profile should specify a metadata property with'\n        note12 = 'name \"osco_version\" and value of the form \"0.1.46\".'\n        note13 = 'The value corresponds with the OpenShift Compliance Operator (OSCO) version'\n        note14 = 'and affects the format of the emitted yaml.'\n        note15 = 'If not specified, the default is \"0.1.46\".'\n        logger.info(f'{note11} {note12} {note13} {note14} {note15}')\n        note21 = '[2] For OSCO version \"0.1.39\" and prior no \"description\" is emitted for \"spec\".'\n        logger.info(f'{note21}')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.warning(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        # check config\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        # input-file\n        input_file = self._config.get('input-file')\n        if input_file is None:\n            logger.warning('config missing \"input-file\"')\n            return TaskOutcome('failure')\n        logger.info(f'input-file: {input_file}')\n        input_path = pathlib.Path(input_file)\n        # output-dir\n        output_dir = self._config.get('output-dir')\n        if output_dir is None:\n            logger.warning('config missing \"output-dir\"')\n            return TaskOutcome('failure')\n        output_path = pathlib.Path(output_dir)\n        # insure output dir exists\n        output_path.mkdir(exist_ok=True, parents=True)\n        # output file path\n        output_name = self._config.get('output-name', 'osco-profile.yaml')\n        output_filepath = pathlib.Path(output_dir, output_name)\n        logger.info(f'output-file: {output_filepath}')\n        # overwrite\n        overwrite = self._config.getboolean('output-overwrite', True)\n        if not overwrite and pathlib.Path(output_filepath).exists():\n            logger.warning(f'output-file: {output_filepath} already exists')\n            return TaskOutcome('failure')\n        # read input\n        profile = Profile.oscal_read(input_path)\n        # transform\n        transformer = OscalProfileToOscoProfileTransformer()\n        ydata = json.loads(transformer.transform(profile))\n        # write output\n        yaml = YAML(typ='safe')\n        yaml.default_flow_style = False\n        with open(output_filepath, 'w') as outfile:\n            yaml.dump(ydata, outfile)\n        # success\n        return TaskOutcome('success')\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task oscal-profile-to-osco-profile.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task oscal-profile-to-osco-profile.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.warning(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Open Security Controls Assessment Language (OSCAL) Profile '\n        + 'into Open Shift Compliance Operator (OSCO) .yaml file.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.oscal-profile-to-osco-profile]:')\n    logger.info('  input-file = (required) path of the input file comprising OSCAL profile.')\n    logger.info('  output-dir = (required) path of the output directory comprising synthesized .yaml file.')\n    logger.info(\n        '  output-name = (optional) name of created file in output directory, default is osco-profile.yaml.'\n    )\n    logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n    logger.info(\n        '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n    )\n    logger.info('')\n    logger.info('Operation: The specified input profile is transformed into OSCO .yaml.')\n    logger.info('')\n    logger.info('Notes:')\n    note11 = '[1] The input-file OSCAL profile should specify a metadata property with'\n    note12 = 'name \"osco_version\" and value of the form \"0.1.46\".'\n    note13 = 'The value corresponds with the OpenShift Compliance Operator (OSCO) version'\n    note14 = 'and affects the format of the emitted yaml.'\n    note15 = 'If not specified, the default is \"0.1.46\".'\n    logger.info(f'{note11} {note12} {note13} {note14} {note15}')\n    note21 = '[2] For OSCO version \"0.1.39\" and prior no \"description\" is emitted for \"spec\".'\n    logger.info(f'{note21}')\n
                                    "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/","title":"osco_result_to_oscal_ar","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar","title":"trestle.tasks.osco_result_to_oscal_ar","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR","title":" OscoResultToOscalAR (TaskBase) ","text":"

                                    Task to convert Osco result to OSCAL json.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                    class OscoResultToOscalAR(TaskBase):\n\"\"\"\n    Task to convert Osco result to OSCAL json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'osco-result-to-oscal-ar'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task osco-result-to-oscal-ar.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Osco files into Open Security Controls Assessment Language (OSCAL) '\n            + 'partial results files.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.osco-result-to-oscal-ar]:')\n        logger.info(\n            '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n        )\n        logger.info('  input-dir = (required) the path of the input directory comprising Osco results.')\n        logger.info(\n            '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n        )\n        logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n        logger.info(\n            '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n        )\n        logger.info(\n            '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n            + ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Osco '\n            + ' result is used if present, otherwise current time is used.'\n        )\n        logger.info('')\n        logger.info(\n            'Operation: A transformation is performed on one or more Osco input files to produce output in OSCAL '\n            + 'partial results format.'\n        )\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        self._simulate = True\n        return self._transform()\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        self._simulate = False\n        return self._transform()\n\n    def _transform(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        try:\n            return self._transform_work()\n        except Exception:\n            logger.debug(traceback.format_exc())\n            mode = ''\n            if self._simulate:\n                mode = 'simulated-'\n            return TaskOutcome(mode + 'failure')\n\n    def _transform_work(self) -> TaskOutcome:\n\"\"\"\n        Perform transformation work steps.\n\n        Work steps: read input, process, write output, display analysis\n        \"\"\"\n        mode = ''\n        if self._simulate:\n            mode = 'simulated-'\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome(mode + 'failure')\n        # config required input & output dirs\n        try:\n            idir = self._config['input-dir']\n            ipth = pathlib.Path(idir)\n            odir = self._config['output-dir']\n            opth = pathlib.Path(odir)\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            return TaskOutcome(mode + 'failure')\n        # config optional overwrite & quiet\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        quiet = self._config.get('quiet', False)\n        self._verbose = not self._simulate and not quiet\n        # config optional timestamp\n        timestamp = self._config.get('timestamp')\n        if timestamp is not None:\n            try:\n                OscoTransformer.set_timestamp(timestamp)\n            except Exception:\n                logger.warning('config invalid \"timestamp\"')\n                return TaskOutcome(mode + 'failure')\n        # config optional performance\n        modes = {\n            'checking': self._config.getboolean('checking', False),\n        }\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # process\n        for ifile in sorted(ipth.iterdir()):\n            if ifile.suffix not in ['.json', '.jsn', '.yaml', '.yml', '.xml']:\n                continue\n            blob = self._read_file(ifile)\n            osco_transformer = OscoTransformer()\n            osco_transformer.set_modes(modes)\n            results = osco_transformer.transform(blob)\n            oname = ifile.stem + '.oscal' + '.json'\n            ofile = opth / oname\n            if not self._overwrite and pathlib.Path(ofile).exists():\n                logger.warning(f'output: {ofile} already exists')\n                return TaskOutcome(mode + 'failure')\n            self._write_file(results, ofile)\n            self._show_analysis(osco_transformer)\n        return TaskOutcome(mode + 'success')\n\n    def _read_file(self, ifile: str) -> str:\n\"\"\"Read raw input file.\"\"\"\n        if not self._simulate and self._verbose:\n            logger.info(f'input: {ifile}')\n        with open(ifile, encoding=const.FILE_ENCODING) as fp:\n            blob = fp.read()\n        return blob\n\n    def _write_file(self, result: str, ofile: str) -> None:\n\"\"\"Write oscal results file.\"\"\"\n        if not self._simulate:\n            if self._verbose:\n                logger.info(f'output: {ofile}')\n            result.oscal_write(pathlib.Path(ofile))\n\n    def _show_analysis(self, osco_transformer: OscoTransformer) -> None:\n\"\"\"Show analysis.\"\"\"\n        if not self._simulate and self._verbose:\n            analysis = osco_transformer.analysis\n            for line in analysis:\n                logger.info(line)\n
                                    "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task osco-result-to-oscal-ar.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task osco-result-to-oscal-ar.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    self._simulate = False\n    return self._transform()\n
                                    "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Osco files into Open Security Controls Assessment Language (OSCAL) '\n        + 'partial results files.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.osco-result-to-oscal-ar]:')\n    logger.info(\n        '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n    )\n    logger.info('  input-dir = (required) the path of the input directory comprising Osco results.')\n    logger.info(\n        '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n    )\n    logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n    logger.info(\n        '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n    )\n    logger.info(\n        '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n        + ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Osco '\n        + ' result is used if present, otherwise current time is used.'\n    )\n    logger.info('')\n    logger.info(\n        'Operation: A transformation is performed on one or more Osco input files to produce output in OSCAL '\n        + 'partial results format.'\n    )\n
                                    "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    self._simulate = True\n    return self._transform()\n
                                    "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/","title":"tanium_result_to_oscal_ar","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar","title":"trestle.tasks.tanium_result_to_oscal_ar","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR","title":" TaniumResultToOscalAR (TaskBase) ","text":"

                                    Task to convert Tanium result to OSCAL json.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                    class TaniumResultToOscalAR(TaskBase):\n\"\"\"\n    Task to convert Tanium result to OSCAL json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'tanium-result-to-oscal-ar'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task tanium-result-to-oscal-ar.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Tanium files into Open Security Controls Assessment Language (OSCAL) results objects'\n            + 'and serialize to a file.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.tanium-result-to-oscal-ar]:')\n        logger.info('  blocksize = (optional) the desired number Tanuim result input lines to process per CPU.')\n        logger.info('  cpus-max  = (optional) the desired maximum number of CPUs to employ, default is 1.')\n        logger.info('  cpus-min  = (optional) the desired minimum number of CPUs to employ.')\n        logger.info('  aggregate = (optional) True indicates employ properties aggregation, default is True.')\n        logger.info('  caching   = (optional) True indicates employ object caching, default is True.')\n        logger.info(\n            '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n        )\n        logger.info('  input-dir = (required) the path of the input directory comprising Tanium results.')\n        logger.info(\n            '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n        )\n        logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n        logger.info(\n            '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n        )\n        logger.info(\n            '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n            + '2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Tanium '\n            + 'result is used if present, otherwise current time is used.'\n        )\n        logger.info('')\n        logger.info(\n            'Operation: A transformation is performed on one or more Tanium input files to produce output in '\n            + 'OSCAL partial results format.'\n        )\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        self._simulate = True\n        return self._transform()\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        self._simulate = False\n        return self._transform()\n\n    def _transform(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        try:\n            return self._transform_work()\n        except Exception:\n            logger.info(traceback.format_exc())\n            mode = ''\n            if self._simulate:\n                mode = 'simulated-'\n            return TaskOutcome(mode + 'failure')\n\n    def _transform_work(self) -> TaskOutcome:\n\"\"\"\n        Perform the transformation work.\n\n        Transformation work steps: read input, process, write output, display analysis.\n        \"\"\"\n        mode = ''\n        if self._simulate:\n            mode = 'simulated-'\n        if not self._config:\n            logger.warning('Config missing')\n            return TaskOutcome(mode + 'failure')\n        # config required input & output dirs\n        try:\n            idir = self._config['input-dir']\n            ipth = pathlib.Path(idir)\n            odir = self._config['output-dir']\n            opth = pathlib.Path(odir)\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            return TaskOutcome(mode + 'failure')\n        # config optional overwrite & quiet\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        quiet = self._config.get('quiet', False)\n        self._verbose = not self._simulate and not quiet\n        # config optional timestamp\n        timestamp = self._config.get('timestamp')\n        if timestamp is not None:\n            try:\n                TaniumTransformer.set_timestamp(timestamp)\n            except Exception:\n                logger.warning('config invalid \"timestamp\"')\n                return TaskOutcome(mode + 'failure')\n        # config optional performance\n        modes = {\n            'blocksize': self._config.getint('blocksize', 10000),\n            'cpus_max': self._config.getint('cpus-max', 1),\n            'cpus_min': self._config.getint('cpus-min', 1),\n            'aggregate': self._config.getboolean('aggregate', True),\n            'caching': self._config.getboolean('caching', True),\n            'checking': self._config.getboolean('checking', False),\n        }\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # process\n        for ifile in sorted(ipth.iterdir()):\n            blob = self._read_file(ifile)\n            tanium_transformer = TaniumTransformer()\n            tanium_transformer.set_modes(modes)\n            results = tanium_transformer.transform(blob)\n            oname = ifile.stem + '.oscal' + '.json'\n            ofile = opth / oname\n            if not self._overwrite and pathlib.Path(ofile).exists():\n                logger.warning(f'output: {ofile} already exists')\n                return TaskOutcome(mode + 'failure')\n            self._write_file(results, ofile)\n            self._show_analysis(tanium_transformer)\n        return TaskOutcome(mode + 'success')\n\n    def _read_file(self, ifile: str) -> str:\n\"\"\"Read raw input file.\"\"\"\n        if not self._simulate and self._verbose:\n            logger.info(f'input: {ifile}')\n        with open(ifile, 'r', encoding=const.FILE_ENCODING) as fp:\n            blob = fp.read()\n        return blob\n\n    def _write_file(self, result: str, ofile: str) -> None:\n\"\"\"Write oscal results file.\"\"\"\n        if not self._simulate:\n            if self._verbose:\n                logger.info(f'output: {ofile}')\n            result.oscal_write(pathlib.Path(ofile))\n\n    def _show_analysis(self, tanium_transformer: TaniumTransformer) -> None:\n\"\"\"Show analysis.\"\"\"\n        if not self._simulate and self._verbose:\n            analysis = tanium_transformer.analysis\n            for line in analysis:\n                logger.info(line)\n
                                    "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task tanium-result-to-oscal-ar.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task tanium-result-to-oscal-ar.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    self._simulate = False\n    return self._transform()\n
                                    "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Tanium files into Open Security Controls Assessment Language (OSCAL) results objects'\n        + 'and serialize to a file.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.tanium-result-to-oscal-ar]:')\n    logger.info('  blocksize = (optional) the desired number Tanuim result input lines to process per CPU.')\n    logger.info('  cpus-max  = (optional) the desired maximum number of CPUs to employ, default is 1.')\n    logger.info('  cpus-min  = (optional) the desired minimum number of CPUs to employ.')\n    logger.info('  aggregate = (optional) True indicates employ properties aggregation, default is True.')\n    logger.info('  caching   = (optional) True indicates employ object caching, default is True.')\n    logger.info(\n        '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n    )\n    logger.info('  input-dir = (required) the path of the input directory comprising Tanium results.')\n    logger.info(\n        '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n    )\n    logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n    logger.info(\n        '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n    )\n    logger.info(\n        '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n        + '2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Tanium '\n        + 'result is used if present, otherwise current time is used.'\n    )\n    logger.info('')\n    logger.info(\n        'Operation: A transformation is performed on one or more Tanium input files to produce output in '\n        + 'OSCAL partial results format.'\n    )\n
                                    "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    self._simulate = True\n    return self._transform()\n
                                    "},{"location":"api_reference/trestle.tasks.transform/","title":"transform","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.transform/#trestle.tasks.transform","title":"trestle.tasks.transform","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/","title":"xccdf_result_to_oscal_ar","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar","title":"trestle.tasks.xccdf_result_to_oscal_ar","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.default_description","title":"default_description","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.default_title","title":"default_title","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.default_type","title":"default_type","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR","title":" XccdfResultToOscalAR (TaskBase) ","text":"

                                    Task to convert Xccdf result to OSCAL json.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                    class XccdfResultToOscalAR(TaskBase):\n\"\"\"\n    Task to convert Xccdf result to OSCAL json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'xccdf-result-to-oscal-ar'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task xccdf-result-to-oscal-ar.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        opt = '(optional)'\n        req = '(required)'\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Xccdf files into Open Security Controls Assessment Language (OSCAL) '\n            + 'partial results files.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.xccdf-result-to-oscal-ar]:')\n        #\n        t1 = f'  input-dir              = {req} '\n        t2 = 'the path of the input directory comprising Xccdf results.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  output-dir             = {req} '\n        t2 = 'the path of the output directory comprising synthesized OSCAL .json files.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  checking               = {opt} '\n        t2 = 'True indicates perform strict checking of OSCAL properties, default is False.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  output-overwrite       = {opt} '\n        t2 = 'true [default] or false; replace existing output when true.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  quiet                  = {opt} '\n        t2 = 'true or false [default]; display file creations and rules analysis when false.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  title                  = {opt} '\n        t2 = f'default={default_title}.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  description            = {opt} '\n        t2 = f'default={default_description}.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  type                   = {opt} '\n        t2 = f'default={default_type}.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  property-name-to-class = {opt} '\n        t2 = 'list of name:class pairs for tagging named property with class, '\n        t3 = 'e.g. \"target:scc_inventory_item_id, version:scc_check_version\".'\n        logger.info(f'{t1}{t2}{t3}')\n        t1 = f'  timestamp              = {opt} '\n        t2 = 'timestamp for the Observations in ISO 8601 format, such as '\n        t3 = ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Xccdf '\n        t4 = ' result is used if present, otherwise current time is used.'\n        logger.info(f'{t1}{t2}{t3}{t4}')\n        #\n        logger.info('')\n        logger.info(\n            'Operation: A transformation is performed on one or more Xccdf input files to produce output in OSCAL '\n            + 'partial results format.'\n        )\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        self._simulate = True\n        return self._transform()\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        self._simulate = False\n        return self._transform()\n\n    def _transform(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        try:\n            return self._transform_work()\n        except Exception:\n            logger.debug(traceback.format_exc())\n            mode = ''\n            if self._simulate:\n                mode = 'simulated-'\n            return TaskOutcome(mode + 'failure')\n\n    def _transform_work(self) -> TaskOutcome:\n\"\"\"\n        Perform transformation work steps.\n\n        Work steps: read input, process, write output, display analysis\n        \"\"\"\n        mode = ''\n        if self._simulate:\n            mode = 'simulated-'\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome(mode + 'failure')\n        # config required input & output dirs\n        try:\n            idir = self._config['input-dir']\n            ipth = pathlib.Path(idir)\n            odir = self._config['output-dir']\n            opth = pathlib.Path(odir)\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            return TaskOutcome(mode + 'failure')\n        # config optional overwrite & quiet\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        quiet = self._config.get('quiet', False)\n        self._verbose = not self._simulate and not quiet\n        # title, description, type\n        title = self._config.get('title', default_title)\n        description = self._config.get('description', default_description)\n        type_ = self._config.get('type', default_type)\n        # property-name-to-class\n        tags = self._get_tags()\n        # config optional timestamp\n        timestamp = self._config.get('timestamp')\n        if timestamp is not None:\n            try:\n                XccdfTransformer.set_timestamp(timestamp)\n            except Exception:\n                logger.warning('config invalid \"timestamp\"')\n                return TaskOutcome(mode + 'failure')\n        # config optional performance\n        modes = {\n            'checking': self._config.getboolean('checking', False),\n        }\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # process\n        for ifile in sorted(ipth.iterdir()):\n            if ifile.suffix not in ['.json', '.jsn', '.yaml', '.yml', '.xml']:\n                continue\n            blob = self._read_file(ifile)\n            xccdf_transformer = XccdfTransformer()\n            xccdf_transformer.set_title(title)\n            xccdf_transformer.set_description(description)\n            xccdf_transformer.set_type(type_)\n            xccdf_transformer.set_modes(modes)\n            xccdf_transformer.set_tags(tags)\n            results = xccdf_transformer.transform(blob)\n            oname = ifile.stem + '.oscal' + '.json'\n            ofile = opth / oname\n            if not self._overwrite and pathlib.Path(ofile).exists():\n                logger.warning(f'output: {ofile} already exists')\n                return TaskOutcome(mode + 'failure')\n            self._write_file(results, ofile)\n            self._show_analysis(xccdf_transformer)\n        return TaskOutcome(mode + 'success')\n\n    def _get_tags(self) -> Dict:\n\"\"\"Get property name to class tags, if any.\"\"\"\n        tags = {}\n        data = self._config.get('property-name-to-class')\n        if data is not None:\n            for item in data.split(','):\n                item = item.strip()\n                parts = item.split(':')\n                if len(parts) == 2:\n                    name = parts[0]\n                    value = parts[1]\n                    tags[name] = value\n        return tags\n\n    def _read_file(self, ifile: str) -> str:\n\"\"\"Read raw input file.\"\"\"\n        if not self._simulate and self._verbose:\n            logger.info(f'input: {ifile}')\n        with open(ifile, encoding=const.FILE_ENCODING) as fp:\n            blob = fp.read()\n        return blob\n\n    def _write_file(self, result: str, ofile: str) -> None:\n\"\"\"Write oscal results file.\"\"\"\n        if not self._simulate:\n            if self._verbose:\n                logger.info(f'output: {ofile}')\n            result.oscal_write(pathlib.Path(ofile))\n\n    def _show_analysis(self, xccdf_transformer: XccdfTransformer) -> None:\n\"\"\"Show analysis.\"\"\"\n        if not self._simulate and self._verbose:\n            analysis = xccdf_transformer.analysis\n            for line in analysis:\n                logger.info(line)\n
                                    "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task xccdf-result-to-oscal-ar.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task xccdf-result-to-oscal-ar.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                    "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.execute","title":"execute(self)","text":"

                                    Provide an actual outcome.

                                    Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    self._simulate = False\n    return self._transform()\n
                                    "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    opt = '(optional)'\n    req = '(required)'\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Xccdf files into Open Security Controls Assessment Language (OSCAL) '\n        + 'partial results files.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.xccdf-result-to-oscal-ar]:')\n    #\n    t1 = f'  input-dir              = {req} '\n    t2 = 'the path of the input directory comprising Xccdf results.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  output-dir             = {req} '\n    t2 = 'the path of the output directory comprising synthesized OSCAL .json files.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  checking               = {opt} '\n    t2 = 'True indicates perform strict checking of OSCAL properties, default is False.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  output-overwrite       = {opt} '\n    t2 = 'true [default] or false; replace existing output when true.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  quiet                  = {opt} '\n    t2 = 'true or false [default]; display file creations and rules analysis when false.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  title                  = {opt} '\n    t2 = f'default={default_title}.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  description            = {opt} '\n    t2 = f'default={default_description}.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  type                   = {opt} '\n    t2 = f'default={default_type}.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  property-name-to-class = {opt} '\n    t2 = 'list of name:class pairs for tagging named property with class, '\n    t3 = 'e.g. \"target:scc_inventory_item_id, version:scc_check_version\".'\n    logger.info(f'{t1}{t2}{t3}')\n    t1 = f'  timestamp              = {opt} '\n    t2 = 'timestamp for the Observations in ISO 8601 format, such as '\n    t3 = ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Xccdf '\n    t4 = ' result is used if present, otherwise current time is used.'\n    logger.info(f'{t1}{t2}{t3}{t4}')\n    #\n    logger.info('')\n    logger.info(\n        'Operation: A transformation is performed on one or more Xccdf input files to produce output in OSCAL '\n        + 'partial results format.'\n    )\n
                                    "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    self._simulate = True\n    return self._transform()\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/","title":"xlsx_helper","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper","title":"trestle.tasks.xlsx_helper","text":"

                                    XLSX utilities.

                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column","title":" Column ","text":"

                                    Spread sheet columns.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    class Column():\n\"\"\"Spread sheet columns.\"\"\"\n\n    control_id = 'ControlId'\n    control_text = 'ControlText'\n    goal_name_id = 'goal_name_id'\n    goal_version = 'goal_version'\n    rule_name_id = 'rule_name_id'\n    rule_version = 'rule_version'\n    nist_mappings = 'NIST Mappings'\n    resource_title = 'ResourceTitle'\n    parameter_opt_parm = 'Parameter [optional parameter]'\n    values_alternatives = 'Values default , [alternatives]'\n    filter_column = None\n\n    tokens_nist_mappings = nist_mappings.split()\n    tokens_parameter_opt_parm = parameter_opt_parm.split()\n    rename_parameter_opt_parm = 'ParameterName'\n    tokens_values_alternatives = values_alternatives.split()\n    rename_values_alternatives = 'ParameterValue'\n\n    help_list = []\n    text1 = '                      '\n    text2 = f'column \"{control_id}\" contains control ID.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{control_text}\" contains control text.'\n    help_list.append(text1 + text2)\n    text2 = f'columns \"{nist_mappings}\" contain NIST control mappings.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{resource_title}\" contains component name.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{goal_name_id}\" contains goal name.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{goal_version}\" contains goal version.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{rule_name_id}\" contains rule name.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{rule_version}\" contains rule version.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{parameter_opt_parm}\" contains parameter name + description, separated by newline.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{values_alternatives}\" contains parameter values.'\n    help_list.append(text1 + text2)\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.control_id","title":"control_id","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.control_text","title":"control_text","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.filter_column","title":"filter_column","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.goal_name_id","title":"goal_name_id","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.goal_version","title":"goal_version","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.help_list","title":"help_list","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.nist_mappings","title":"nist_mappings","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.parameter_opt_parm","title":"parameter_opt_parm","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rename_parameter_opt_parm","title":"rename_parameter_opt_parm","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rename_values_alternatives","title":"rename_values_alternatives","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.resource_title","title":"resource_title","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rule_name_id","title":"rule_name_id","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rule_version","title":"rule_version","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.text1","title":"text1","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.text2","title":"text2","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.tokens_nist_mappings","title":"tokens_nist_mappings","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.tokens_parameter_opt_parm","title":"tokens_parameter_opt_parm","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.tokens_values_alternatives","title":"tokens_values_alternatives","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.values_alternatives","title":"values_alternatives","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper","title":" XlsxHelper ","text":"

                                    Xlsx Helper common functions and assistance navigating spread sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    class XlsxHelper:\n\"\"\"Xlsx Helper common functions and assistance navigating spread sheet.\"\"\"\n\n    by_goal = 'by-goal'\n    by_rule = 'by-rule'\n    by_control = 'by-control'\n    by_check = 'by-check'\n\n    profile_types = [by_goal, by_rule, by_control, by_check]\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._column = Column()\n\n    def print_info(self, name, oscal_name) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {name} task.')\n        logger.info('')\n        logger.info(f'Purpose: From spread sheet and catalog produce OSCAL {oscal_name} file.')\n        logger.info('')\n        logger.info(f'Configuration flags sit under [task.{name}]:')\n        if oscal_name == 'component_definition':\n            text1 = '  catalog-file      = '\n            text2 = '(required) the path of the OSCAL catalog file.'\n            logger.info(text1 + text2)\n        text1 = '  spread-sheet-file = '\n        text2 = '(required) the path of the spread sheet file.'\n        logger.info(text1 + text2)\n        text1 = '  work-sheet-name   = '\n        text2 = '(required) the name of the work sheet in the spread sheet file.'\n        logger.info(text1 + text2)\n        for line in self._column.help_list:\n            logger.info(line)\n        text1 = '  output-dir        = '\n        text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite  = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n        text1 = '  filter-column     = '\n        text2 = '(optional) column heading of yes/no values; process only \"yes\" rows.'\n        logger.info(text1 + text2)\n        text1 = '  profile-type      = '\n        text2 = f'(optional) one of {self.profile_types}'\n        logger.info(text1 + text2)\n\n    @property\n    def profile_type(self) -> str:\n\"\"\"Profile type.\"\"\"\n        return self._profile_type\n\n    def configure(self, task: TaskBase) -> bool:\n\"\"\"Configure.\"\"\"\n        if not task._config:\n            logger.warning('config missing')\n            return False\n        # config verbosity\n        quiet = task._config.get('quiet', False)\n        task._verbose = not quiet\n        # required for component-definition\n        if not self.configure_cd(task):\n            return False\n        # required for profile\n        if not self.configure_profile(task):\n            return False\n        # optional\n        self._column.filter_column = task._config.get('filter-column', None)\n        # config spread sheet\n        spread_sheet = task._config.get('spread-sheet-file')\n        if spread_sheet is None:\n            logger.warning('config missing \"spread-sheet\"')\n            return False\n        if not pathlib.Path(spread_sheet).exists():\n            logger.warning('\"spread-sheet\" not found')\n            return False\n        sheet_name = task._config.get('work-sheet-name')\n        if sheet_name is None:\n            logger.warning('config missing \"work-sheet-name\"')\n            return False\n        # announce spreadsheet\n        if task._verbose:\n            logger.info(f'input: {spread_sheet}')\n        # get profile type\n        if task.name == 'xlsx-to-oscal-profile':\n            self._profile_type = task._config.get('profile-type', self.profile_types[0])\n            if self._profile_type not in self.profile_types:\n                logger.warning(f'invalid \"profile-type\" {self._profile_type} ')\n                return False\n        else:\n            self._profile_type = None\n        # load spread sheet\n        self.load(spread_sheet, sheet_name)\n        return True\n\n    def configure_cd(self, task: TaskBase) -> bool:\n\"\"\"Configure cd.\"\"\"\n        if task.name == 'xlsx-to-oscal-cd':\n            catalog_file = task._config.get('catalog-file')\n            if catalog_file is None:\n                logger.warning('config missing \"catalog-file\"')\n                return False\n            try:\n                catalog = Catalog.oscal_read(pathlib.Path(catalog_file))\n                logger.debug(f'catalog: {catalog_file}')\n            except Exception as e:  # pragma: no cover\n                raise TrestleError(f'Error loading catalog {catalog_file}: {e}')\n            task.catalog_interface = CatalogInterface(catalog)\n        return True\n\n    def configure_profile(self, task: TaskBase) -> bool:\n\"\"\"Configure profile.\"\"\"\n        if task.name == 'xlsx-to-oscal-profile':\n            profile_title = task._config.get('profile-title')\n            if profile_title is None:\n                logger.warning('config missing \"profile-title\"')\n                return False\n            spread_sheet_url = task._config.get('spread-sheet-url')\n            if spread_sheet_url is None:\n                logger.warning('config missing \"spread-sheet-url\"')\n                return False\n        return True\n\n    def load(self, spread_sheet: str, sheet_name: str) -> None:\n\"\"\"Load.\"\"\"\n        self._spread_sheet = spread_sheet\n        self._sheet_name = sheet_name\n        self._wb = load_workbook(self._spread_sheet)\n        self._work_sheet = self._wb[self._sheet_name]\n        self._map_name_to_letters = {}\n        # accumulators\n        self.rows_missing_control_id = []\n        self.rows_missing_goal_name_id = []\n        self.rows_invalid_goal_name_id = []\n        self.rows_missing_rule_name_id = []\n        self.rows_invalid_rule_name_id = []\n        self.rows_invalid_parameter_name = []\n        self.rows_missing_controls = []\n        self.rows_missing_parameters = []\n        self.rows_missing_parameters_values = []\n        self.rows_filtered = []\n        # map columns\n        self._map_columns()\n\n    def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until control_id is None.\"\"\"\n        row = 1\n        rows_skipped_consecutive = 0\n        # assume no more data when 100 consecutve rows no control id\n        rows_skipped_consecutive_limit = 100\n        while True:\n            row = row + 1\n            control_id = self._get_control_id(row)\n            goal_id = self.get_goal_name_id(row)\n            if control_id is None and goal_id is None:\n                rows_skipped_consecutive += 1\n                if rows_skipped_consecutive < rows_skipped_consecutive_limit:\n                    continue\n                logger.debug(f'break: {row} {rows_skipped_consecutive}')\n                break\n            if control_id is None:\n                self._add_row(row, self.rows_missing_control_id)\n                continue\n            if goal_id is None:\n                self._add_row(row, self.rows_missing_goal_name_id)\n                continue\n            if self._is_filtered(row):\n                continue\n            yield row\n            rows_skipped_consecutive = 0\n\n    def _is_filtered(self, row) -> bool:\n\"\"\"Return True if row is to be skipped.\"\"\"\n        if self._column.filter_column is None:\n            return False\n        col = self._get_column_letter(self._column.filter_column)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            return False\n        if value.lower() != 'yes':\n            return False\n        self._add_row(row, self.rows_filtered)\n        return True\n\n    def get_goal_name_id(self, row: int, strict: bool = True) -> str:\n\"\"\"Get goal_name_id from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.goal_name_id)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            self._add_row(row, self.rows_missing_goal_name_id)\n        else:\n            value = str(value).strip()\n            if strict:\n                svalue = str(value).strip()\n                value = ''.join(str(svalue).split())\n                if value != svalue:\n                    self._add_row(row, self.rows_invalid_goal_name_id)\n        return value\n\n    def get_check_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get check_name_id from work_sheet.\"\"\"\n        return self.get_goal_name_id(row, strict)\n\n    def get_rule_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get rule_name_id from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.rule_name_id)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            self._add_row(row, self.rows_missing_rule_name_id)\n        else:\n            value = str(value).strip()\n            if strict:\n                svalue = str(value).strip()\n                value = ''.join(str(svalue).split())\n                if value != svalue:\n                    self._add_row(row, self.rows_invalid_rule_name_id)\n        return value\n\n    def get_parameter_usage(self, row: int) -> str:\n\"\"\"Get parameter_usage from work_sheet.\"\"\"\n        return self.get_goal_remarks(row)\n\n    def get_parameter_value_default(self, row: int) -> str:\n\"\"\"Get parameter_value_default from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.rename_values_alternatives)\n        value = self._work_sheet[col + str(row)].value\n        if value is not None:\n            value = str(value).split(',')[0].strip()\n        return value\n\n    def get_parameter_values(self, row: int) -> str:\n\"\"\"Get parameter_values from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.rename_values_alternatives)\n        value = self._work_sheet[col + str(row)].value\n        if value is None and self.get_parameter_name(row) is not None:\n            self._add_row(row, self.rows_missing_parameters_values)\n        # massage into comma separated list of values\n        else:\n            value = str(value).strip().replace(' ', '')\n            value = value.replace(',[]', '')\n            value = value.replace('[', '')\n            value = value.replace(']', '')\n            value = value.split(',')\n        return value\n\n    def _get_goal_text(self, row: int) -> str:\n\"\"\"Get goal_text from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.control_text)\n        goal_text = self._work_sheet[col + str(row)].value\n        # normalize & tokenize\n        value = goal_text.replace('\\t', ' ')\n        return value\n\n    def _get_goal_text_tokens(self, row: int) -> List[str]:\n\"\"\"Get goal_text tokens from work_sheet.\"\"\"\n        goal_text = self._get_goal_text(row)\n        tokens = goal_text.split()\n        return tokens\n\n    def get_goal_remarks(self, row: int) -> str:\n\"\"\"Get goal_remarks from work_sheet.\"\"\"\n        tokens = self._get_goal_text_tokens(row)\n        # replace \"Check whether\" with \"Ensure\", if present\n        if tokens:\n            if tokens[0] == 'Check':\n                if len(tokens) > 1:\n                    if tokens[1] == 'whether':\n                        tokens.pop(0)\n                tokens[0] = 'Ensure'\n        value = ' '.join(tokens)\n        return value\n\n    def get_controls(self, row: int) -> Dict[str, List[str]]:\n\"\"\"Produce dict of controls mapped to statements.\n\n        Example: {'au-2': ['(a)', '(d)'], 'au-12': [], 'si-4': ['(a)', '(b)', '(c)']}\n        \"\"\"\n        value = {}\n        for col in self._get_column_letter(self._column.nist_mappings):\n            control = self._work_sheet[col + str(row)].value\n            if control is None:\n                continue\n            # remove blanks\n            control = ''.join(control.split())\n            if len(control) < 1 or control.lower() == 'none':\n                continue\n            # remove rhs of : inclusive\n            if ':' in control:\n                control = control.split(':')[0]\n            # remove alphabet parts of control & accumulate in statements\n            control, statements = self._normalize_control(control)\n            # skip bogus control made up if dashes only\n            if len(control.replace('-', '')) == 0:\n                continue\n            if control not in value.keys():\n                value[control] = statements\n        if len(value.keys()) == 0:\n            self._add_row(row, self.rows_missing_controls)\n        logger.debug(f'row: {row} controls {value}')\n        return value\n\n    def get_component_name(self, row: int) -> str:\n\"\"\"Get component_name from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.resource_title)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            raise RuntimeError(f'row {row} col {col} missing component name')\n        return value.strip()\n\n    def get_parameter_name(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name from work_sheet.\"\"\"\n        return self.get_parameter_name_and_description(row)[0]\n\n    def get_parameter_name_and_description(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name and description from work_sheet.\"\"\"\n        name = None\n        description = None\n        col = self._get_column_letter(self._column.rename_parameter_opt_parm)\n        combined_values = self._work_sheet[col + str(row)].value\n        if combined_values is not None:\n            if '\\n' in combined_values:\n                parameter_parts = combined_values.split('\\n')\n            elif ' ' in combined_values:\n                parameter_parts = combined_values.split(' ', 1)\n            else:\n                parameter_parts = combined_values\n            if len(parameter_parts) == 2:\n                name = parameter_parts[1].strip()\n                description = parameter_parts[0].strip()\n                sname = str(name).strip()\n                name = sname.replace(' ', '_')\n                if name != sname:\n                    self._add_row(row, self.rows_invalid_parameter_name)\n            else:\n                logger.info(f'row {row} col {col} invalid value')\n        if name is None and self.get_parameter_value_default(row) is not None:\n            self._add_row(row, self.rows_missing_parameters)\n        value = name, description\n        return value\n\n    def _get_control_id(self, row: int) -> int:\n\"\"\"Get control_id from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.control_id)\n        value = self._work_sheet[col + str(row)].value\n        return value\n\n    def _get_column_letter(self, name: str) -> str:\n\"\"\"Get column letter.\"\"\"\n        value = self.map_name_to_letters[name]\n        if len(value) == 1:\n            value = value[0]\n        return value\n\n    def _map_columns(self) -> None:\n\"\"\"Map columns.\"\"\"\n        self.map_name_to_letters = {}\n        columns = self._work_sheet.max_column\n        for column in range(1, columns + 1):\n            cell_value = self._cell_value(1, column)\n            if cell_value is None:\n                continue\n            cell_tokens = cell_value.split()\n            normalized_cell_value = ' '.join(cell_tokens)\n            # find columns of interest\n            if self._column.control_id in cell_tokens:\n                self._add_column(self._column.control_id, column, 1)\n            elif self._column.control_text in cell_tokens:\n                self._add_column(self._column.control_text, column, 1)\n            elif self._column.goal_name_id in cell_tokens:\n                self._add_column(self._column.goal_name_id, column, 1)\n            elif self._column.goal_version in cell_tokens:\n                self._add_column(self._column.goal_version, column, 1)\n            elif self._column.rule_name_id in cell_tokens:\n                self._add_column(self._column.rule_name_id, column, 1)\n            elif self._column.rule_version in cell_tokens:\n                self._add_column(self._column.rule_version, column, 1)\n            # parameters and alternatives (exact tokens match)\n            elif cell_tokens == self._column.tokens_parameter_opt_parm:\n                self._add_column(self._column.rename_parameter_opt_parm, column, 1)\n            elif cell_tokens == self._column.tokens_values_alternatives:\n                self._add_column(self._column.rename_values_alternatives, column, 1)\n            # filter column (exact string match)\n            elif self._column.filter_column == normalized_cell_value:\n                self._add_column(self._column.filter_column, column, 1)\n            # nist mappings and resource title (multiple columns match)\n            elif is_ordered_sublist(self._column.tokens_nist_mappings, cell_tokens):\n                self._add_column(self._column.nist_mappings, column, 0)\n            elif self._column.resource_title in cell_tokens:\n                self._add_column(self._column.resource_title, column, 0)\n        # insure expected columns found\n        for name in [self._column.control_id,\n                     self._column.control_text,\n                     self._column.rule_name_id,\n                     self._column.rule_version,\n                     self._column.goal_name_id,\n                     self._column.goal_version,\n                     self._column.nist_mappings,\n                     self._column.resource_title,\n                     self._column.rename_parameter_opt_parm,\n                     self._column.rename_values_alternatives]:\n            if name not in self.map_name_to_letters.keys():\n                raise RuntimeError(f'missing column {name}')\n\n    def _add_column(self, name: str, column: int, limit: int) -> None:\n\"\"\"Add column.\"\"\"\n        if name not in self.map_name_to_letters:\n            self.map_name_to_letters[name] = []\n        if limit > 0 and len(self.map_name_to_letters[name]) == limit:\n            raise RuntimeError(f'duplicate column {name} {get_column_letter(column)}')\n        self.map_name_to_letters[name].append(get_column_letter(column))\n\n    def _cell_value(self, row: int, col: int) -> Any:\n\"\"\"Get value for cell, adjusting for merged cells.\"\"\"\n        cell = self._work_sheet.cell(row, col)\n        retval = cell.value\n        if isinstance(cell, MergedCell):\n            # cell is merged\n            for mc_range in self._work_sheet.merged_cells.ranges:\n                coord = get_column_letter(col) + str(row)\n                if coord in mc_range:\n                    retval = mc_range.start_cell.value\n        return retval\n\n    def _normalize_control(self, control: str) -> Tuple[str, List[str]]:\n\"\"\"Remove parenthesized characters from controls.\"\"\"\n        statements = []\n        for i in string.ascii_lowercase:\n            needle = '(' + i + ')'\n            if needle in control:\n                statements.append(needle)\n                control = control.replace(needle, '')\n        control = control.lower()\n        return control, statements\n\n    def _add_row(self, row: int, account: List[int]) -> None:\n\"\"\"Add row to accounting list of rows.\"\"\"\n        if row not in account:\n            account.append(row)\n\n    def report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n        if self.rows_missing_control_id:\n            logger.info(f'rows missing control_id: {self.rows_missing_control_id}')\n        if self.rows_invalid_goal_name_id:\n            logger.info(f'rows invalid goal_name_id: {self.rows_invalid_goal_name_id}')\n        if self.rows_missing_rule_name_id:\n            logger.info(f'rows missing rule_name_id: {self.rows_missing_rule_name_id}')\n        if self.rows_invalid_rule_name_id:\n            logger.info(f'rows invalid rule_name_id: {self.rows_invalid_rule_name_id}')\n        if self.rows_invalid_parameter_name:\n            logger.info(f'rows invalid parameter_name: {self.rows_invalid_parameter_name}')\n        if self.rows_missing_controls:\n            logger.info(f'rows missing controls: {self.rows_missing_controls}')\n        if self.rows_missing_parameters:\n            logger.info(f'rows missing parameters: {self.rows_missing_parameters}')\n        if self.rows_missing_parameters_values:\n            logger.info(f'rows missing parameters values: {self.rows_missing_parameters_values}')\n        if self.rows_filtered:\n            logger.info(f'rows filtered: {self.rows_filtered}')\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_check","title":"by_check","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_control","title":"by_control","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_goal","title":"by_goal","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_rule","title":"by_rule","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.profile_type","title":"profile_type: str property readonly","text":"

                                    Profile type.

                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.profile_types","title":"profile_types","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.__init__","title":"__init__(self) special","text":"

                                    Initialize.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._column = Column()\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.configure","title":"configure(self, task)","text":"

                                    Configure.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def configure(self, task: TaskBase) -> bool:\n\"\"\"Configure.\"\"\"\n    if not task._config:\n        logger.warning('config missing')\n        return False\n    # config verbosity\n    quiet = task._config.get('quiet', False)\n    task._verbose = not quiet\n    # required for component-definition\n    if not self.configure_cd(task):\n        return False\n    # required for profile\n    if not self.configure_profile(task):\n        return False\n    # optional\n    self._column.filter_column = task._config.get('filter-column', None)\n    # config spread sheet\n    spread_sheet = task._config.get('spread-sheet-file')\n    if spread_sheet is None:\n        logger.warning('config missing \"spread-sheet\"')\n        return False\n    if not pathlib.Path(spread_sheet).exists():\n        logger.warning('\"spread-sheet\" not found')\n        return False\n    sheet_name = task._config.get('work-sheet-name')\n    if sheet_name is None:\n        logger.warning('config missing \"work-sheet-name\"')\n        return False\n    # announce spreadsheet\n    if task._verbose:\n        logger.info(f'input: {spread_sheet}')\n    # get profile type\n    if task.name == 'xlsx-to-oscal-profile':\n        self._profile_type = task._config.get('profile-type', self.profile_types[0])\n        if self._profile_type not in self.profile_types:\n            logger.warning(f'invalid \"profile-type\" {self._profile_type} ')\n            return False\n    else:\n        self._profile_type = None\n    # load spread sheet\n    self.load(spread_sheet, sheet_name)\n    return True\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.configure_cd","title":"configure_cd(self, task)","text":"

                                    Configure cd.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def configure_cd(self, task: TaskBase) -> bool:\n\"\"\"Configure cd.\"\"\"\n    if task.name == 'xlsx-to-oscal-cd':\n        catalog_file = task._config.get('catalog-file')\n        if catalog_file is None:\n            logger.warning('config missing \"catalog-file\"')\n            return False\n        try:\n            catalog = Catalog.oscal_read(pathlib.Path(catalog_file))\n            logger.debug(f'catalog: {catalog_file}')\n        except Exception as e:  # pragma: no cover\n            raise TrestleError(f'Error loading catalog {catalog_file}: {e}')\n        task.catalog_interface = CatalogInterface(catalog)\n    return True\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.configure_profile","title":"configure_profile(self, task)","text":"

                                    Configure profile.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def configure_profile(self, task: TaskBase) -> bool:\n\"\"\"Configure profile.\"\"\"\n    if task.name == 'xlsx-to-oscal-profile':\n        profile_title = task._config.get('profile-title')\n        if profile_title is None:\n            logger.warning('config missing \"profile-title\"')\n            return False\n        spread_sheet_url = task._config.get('spread-sheet-url')\n        if spread_sheet_url is None:\n            logger.warning('config missing \"spread-sheet-url\"')\n            return False\n    return True\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_check_name_id","title":"get_check_name_id(self, row, strict=False)","text":"

                                    Get check_name_id from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_check_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get check_name_id from work_sheet.\"\"\"\n    return self.get_goal_name_id(row, strict)\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_component_name","title":"get_component_name(self, row)","text":"

                                    Get component_name from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_component_name(self, row: int) -> str:\n\"\"\"Get component_name from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.resource_title)\n    value = self._work_sheet[col + str(row)].value\n    if value is None:\n        raise RuntimeError(f'row {row} col {col} missing component name')\n    return value.strip()\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_controls","title":"get_controls(self, row)","text":"

                                    Produce dict of controls mapped to statements.

                                    Example: {'au-2': ['(a)', '(d)'], 'au-12': [], 'si-4': ['(a)', '(b)', '(c)']}

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_controls(self, row: int) -> Dict[str, List[str]]:\n\"\"\"Produce dict of controls mapped to statements.\n\n    Example: {'au-2': ['(a)', '(d)'], 'au-12': [], 'si-4': ['(a)', '(b)', '(c)']}\n    \"\"\"\n    value = {}\n    for col in self._get_column_letter(self._column.nist_mappings):\n        control = self._work_sheet[col + str(row)].value\n        if control is None:\n            continue\n        # remove blanks\n        control = ''.join(control.split())\n        if len(control) < 1 or control.lower() == 'none':\n            continue\n        # remove rhs of : inclusive\n        if ':' in control:\n            control = control.split(':')[0]\n        # remove alphabet parts of control & accumulate in statements\n        control, statements = self._normalize_control(control)\n        # skip bogus control made up if dashes only\n        if len(control.replace('-', '')) == 0:\n            continue\n        if control not in value.keys():\n            value[control] = statements\n    if len(value.keys()) == 0:\n        self._add_row(row, self.rows_missing_controls)\n    logger.debug(f'row: {row} controls {value}')\n    return value\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_goal_name_id","title":"get_goal_name_id(self, row, strict=True)","text":"

                                    Get goal_name_id from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_goal_name_id(self, row: int, strict: bool = True) -> str:\n\"\"\"Get goal_name_id from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.goal_name_id)\n    value = self._work_sheet[col + str(row)].value\n    if value is None:\n        self._add_row(row, self.rows_missing_goal_name_id)\n    else:\n        value = str(value).strip()\n        if strict:\n            svalue = str(value).strip()\n            value = ''.join(str(svalue).split())\n            if value != svalue:\n                self._add_row(row, self.rows_invalid_goal_name_id)\n    return value\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_goal_remarks","title":"get_goal_remarks(self, row)","text":"

                                    Get goal_remarks from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_goal_remarks(self, row: int) -> str:\n\"\"\"Get goal_remarks from work_sheet.\"\"\"\n    tokens = self._get_goal_text_tokens(row)\n    # replace \"Check whether\" with \"Ensure\", if present\n    if tokens:\n        if tokens[0] == 'Check':\n            if len(tokens) > 1:\n                if tokens[1] == 'whether':\n                    tokens.pop(0)\n            tokens[0] = 'Ensure'\n    value = ' '.join(tokens)\n    return value\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_name","title":"get_parameter_name(self, row)","text":"

                                    Get parameter_name from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_parameter_name(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name from work_sheet.\"\"\"\n    return self.get_parameter_name_and_description(row)[0]\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_name_and_description","title":"get_parameter_name_and_description(self, row)","text":"

                                    Get parameter_name and description from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_parameter_name_and_description(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name and description from work_sheet.\"\"\"\n    name = None\n    description = None\n    col = self._get_column_letter(self._column.rename_parameter_opt_parm)\n    combined_values = self._work_sheet[col + str(row)].value\n    if combined_values is not None:\n        if '\\n' in combined_values:\n            parameter_parts = combined_values.split('\\n')\n        elif ' ' in combined_values:\n            parameter_parts = combined_values.split(' ', 1)\n        else:\n            parameter_parts = combined_values\n        if len(parameter_parts) == 2:\n            name = parameter_parts[1].strip()\n            description = parameter_parts[0].strip()\n            sname = str(name).strip()\n            name = sname.replace(' ', '_')\n            if name != sname:\n                self._add_row(row, self.rows_invalid_parameter_name)\n        else:\n            logger.info(f'row {row} col {col} invalid value')\n    if name is None and self.get_parameter_value_default(row) is not None:\n        self._add_row(row, self.rows_missing_parameters)\n    value = name, description\n    return value\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_usage","title":"get_parameter_usage(self, row)","text":"

                                    Get parameter_usage from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_parameter_usage(self, row: int) -> str:\n\"\"\"Get parameter_usage from work_sheet.\"\"\"\n    return self.get_goal_remarks(row)\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_value_default","title":"get_parameter_value_default(self, row)","text":"

                                    Get parameter_value_default from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_parameter_value_default(self, row: int) -> str:\n\"\"\"Get parameter_value_default from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.rename_values_alternatives)\n    value = self._work_sheet[col + str(row)].value\n    if value is not None:\n        value = str(value).split(',')[0].strip()\n    return value\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_values","title":"get_parameter_values(self, row)","text":"

                                    Get parameter_values from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_parameter_values(self, row: int) -> str:\n\"\"\"Get parameter_values from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.rename_values_alternatives)\n    value = self._work_sheet[col + str(row)].value\n    if value is None and self.get_parameter_name(row) is not None:\n        self._add_row(row, self.rows_missing_parameters_values)\n    # massage into comma separated list of values\n    else:\n        value = str(value).strip().replace(' ', '')\n        value = value.replace(',[]', '')\n        value = value.replace('[', '')\n        value = value.replace(']', '')\n        value = value.split(',')\n    return value\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_rule_name_id","title":"get_rule_name_id(self, row, strict=False)","text":"

                                    Get rule_name_id from work_sheet.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_rule_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get rule_name_id from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.rule_name_id)\n    value = self._work_sheet[col + str(row)].value\n    if value is None:\n        self._add_row(row, self.rows_missing_rule_name_id)\n    else:\n        value = str(value).strip()\n        if strict:\n            svalue = str(value).strip()\n            value = ''.join(str(svalue).split())\n            if value != svalue:\n                self._add_row(row, self.rows_invalid_rule_name_id)\n    return value\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.load","title":"load(self, spread_sheet, sheet_name)","text":"

                                    Load.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def load(self, spread_sheet: str, sheet_name: str) -> None:\n\"\"\"Load.\"\"\"\n    self._spread_sheet = spread_sheet\n    self._sheet_name = sheet_name\n    self._wb = load_workbook(self._spread_sheet)\n    self._work_sheet = self._wb[self._sheet_name]\n    self._map_name_to_letters = {}\n    # accumulators\n    self.rows_missing_control_id = []\n    self.rows_missing_goal_name_id = []\n    self.rows_invalid_goal_name_id = []\n    self.rows_missing_rule_name_id = []\n    self.rows_invalid_rule_name_id = []\n    self.rows_invalid_parameter_name = []\n    self.rows_missing_controls = []\n    self.rows_missing_parameters = []\n    self.rows_missing_parameters_values = []\n    self.rows_filtered = []\n    # map columns\n    self._map_columns()\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.print_info","title":"print_info(self, name, oscal_name)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def print_info(self, name, oscal_name) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {name} task.')\n    logger.info('')\n    logger.info(f'Purpose: From spread sheet and catalog produce OSCAL {oscal_name} file.')\n    logger.info('')\n    logger.info(f'Configuration flags sit under [task.{name}]:')\n    if oscal_name == 'component_definition':\n        text1 = '  catalog-file      = '\n        text2 = '(required) the path of the OSCAL catalog file.'\n        logger.info(text1 + text2)\n    text1 = '  spread-sheet-file = '\n    text2 = '(required) the path of the spread sheet file.'\n    logger.info(text1 + text2)\n    text1 = '  work-sheet-name   = '\n    text2 = '(required) the name of the work sheet in the spread sheet file.'\n    logger.info(text1 + text2)\n    for line in self._column.help_list:\n        logger.info(line)\n    text1 = '  output-dir        = '\n    text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite  = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n    text1 = '  filter-column     = '\n    text2 = '(optional) column heading of yes/no values; process only \"yes\" rows.'\n    logger.info(text1 + text2)\n    text1 = '  profile-type      = '\n    text2 = f'(optional) one of {self.profile_types}'\n    logger.info(text1 + text2)\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.report_issues","title":"report_issues(self)","text":"

                                    Report issues.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n    if self.rows_missing_control_id:\n        logger.info(f'rows missing control_id: {self.rows_missing_control_id}')\n    if self.rows_invalid_goal_name_id:\n        logger.info(f'rows invalid goal_name_id: {self.rows_invalid_goal_name_id}')\n    if self.rows_missing_rule_name_id:\n        logger.info(f'rows missing rule_name_id: {self.rows_missing_rule_name_id}')\n    if self.rows_invalid_rule_name_id:\n        logger.info(f'rows invalid rule_name_id: {self.rows_invalid_rule_name_id}')\n    if self.rows_invalid_parameter_name:\n        logger.info(f'rows invalid parameter_name: {self.rows_invalid_parameter_name}')\n    if self.rows_missing_controls:\n        logger.info(f'rows missing controls: {self.rows_missing_controls}')\n    if self.rows_missing_parameters:\n        logger.info(f'rows missing parameters: {self.rows_missing_parameters}')\n    if self.rows_missing_parameters_values:\n        logger.info(f'rows missing parameters values: {self.rows_missing_parameters_values}')\n    if self.rows_filtered:\n        logger.info(f'rows filtered: {self.rows_filtered}')\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.row_generator","title":"row_generator(self)","text":"

                                    Generate rows until control_id is None.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until control_id is None.\"\"\"\n    row = 1\n    rows_skipped_consecutive = 0\n    # assume no more data when 100 consecutve rows no control id\n    rows_skipped_consecutive_limit = 100\n    while True:\n        row = row + 1\n        control_id = self._get_control_id(row)\n        goal_id = self.get_goal_name_id(row)\n        if control_id is None and goal_id is None:\n            rows_skipped_consecutive += 1\n            if rows_skipped_consecutive < rows_skipped_consecutive_limit:\n                continue\n            logger.debug(f'break: {row} {rows_skipped_consecutive}')\n            break\n        if control_id is None:\n            self._add_row(row, self.rows_missing_control_id)\n            continue\n        if goal_id is None:\n            self._add_row(row, self.rows_missing_goal_name_id)\n            continue\n        if self._is_filtered(row):\n            continue\n        yield row\n        rows_skipped_consecutive = 0\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper-functions","title":"Functions","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.get_trestle_version","title":"get_trestle_version()","text":"

                                    Get trestle version wrapper.

                                    Source code in trestle/tasks/xlsx_helper.py
                                    def get_trestle_version() -> str:\n\"\"\"Get trestle version wrapper.\"\"\"\n    return __version__\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/","title":"xlsx_to_oscal_cd","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd","title":"trestle.tasks.xlsx_to_oscal_cd","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.key_sep","title":"key_sep","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.sep","title":"sep","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition","title":" XlsxToOscalComponentDefinition (TaskBase) ","text":"

                                    Task to create OSCAL ComponentDefinition json.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                    class XlsxToOscalComponentDefinition(TaskBase):\n\"\"\"\n    Task to create OSCAL ComponentDefinition json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'xlsx-to-oscal-cd'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task xlsx-to-oscal-cd.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self.xlsx_helper = XlsxHelper()\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n        self._timestamp = timestamp\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        self.xlsx_helper.print_info(self.name, 'component_definition')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Execute path core.\"\"\"\n        if not self.xlsx_helper.configure(self):\n            return TaskOutcome('failure')\n        # config output\n        odir = self._config.get('output-dir')\n        opth = pathlib.Path(odir)\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'component-definition.json'\n        ofile = opth / oname\n        if not self._overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # initialize\n        self.defined_components = {}\n        # roles, responsible_roles, parties, responsible parties\n        party_uuid_01 = str(uuid.uuid4())\n        party_uuid_02 = str(uuid.uuid4())\n        party_uuid_03 = str(uuid.uuid4())\n        roles = self._build_roles()\n        responsible_roles = self._build_responsible_roles(party_uuid_01, party_uuid_02, party_uuid_03)\n        parties = self._build_parties(party_uuid_01, party_uuid_02, party_uuid_03)\n        responsible_parties = self._build_responsible_parties(party_uuid_01, party_uuid_02, party_uuid_03)\n        # process each row of spread sheet\n        self._process_rows(responsible_roles)\n        # create OSCAL ComponentDefinition\n        metadata = Metadata(\n            title='Component definition for ' + self._get_catalog_title() + ' profiles',\n            last_modified=self._timestamp,\n            oscal_version=OSCAL_VERSION,\n            version=get_trestle_version(),\n            roles=roles,\n            parties=parties,\n            responsible_parties=responsible_parties\n        )\n        component_definition = ComponentDefinition(\n            uuid=str(uuid.uuid4()),\n            metadata=metadata,\n            components=list(self.defined_components.values()),\n        )\n        # write OSCAL ComponentDefinition to file\n        if self._verbose:\n            logger.info(f'output: {ofile}')\n        component_definition.oscal_write(pathlib.Path(ofile))\n        # issues\n        self._report_issues()\n        return TaskOutcome('success')\n\n    def _process_rows(self, responsible_roles: List[ResponsibleRole]) -> None:\n\"\"\"Process spread sheet rows.\"\"\"\n        ci_map = {}\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            goal_name_id = self.xlsx_helper.get_goal_name_id(row)\n            controls = self.xlsx_helper.get_controls(row)\n            if len(controls.keys()) == 0:\n                continue\n            # component\n            component_name = self.xlsx_helper.get_component_name(row)\n            component_type = 'Service'\n            defined_component = self._get_defined_component(component_name, component_type)\n            # parameter\n            parameter_name, parameter_description = self.xlsx_helper.get_parameter_name_and_description(row)\n            # control implementations\n            source = self._get_catalog_url()\n            description = component_name + ' implemented controls for ' + self._get_catalog_title(\n            ) + '. It includes assessment asset configuration for CICD.'\n            key = source + key_sep + description\n            control_implementation = ci_map.get(key)\n            if not control_implementation:\n                ci_map[key] = ControlImplementation(\n                    uuid=str(uuid.uuid4()),\n                    source=source,\n                    description=description,\n                    implemented_requirements=[],\n                )\n                control_implementation = ci_map[key]\n                if defined_component.control_implementations is None:\n                    defined_component.control_implementations = []\n                defined_component.control_implementations.append(control_implementation)\n            # implemented requirements\n            self._add_implemented_requirements(\n                row, control_implementation, controls, component_name, parameter_name, responsible_roles, goal_name_id\n            )\n            # keep alternative parameter values at control implementation level\n            parameter_values = self.xlsx_helper.get_parameter_values(row)\n            self._add_set_parameter_values(parameter_name, parameter_values, control_implementation)\n\n    def _add_implemented_requirements(\n        self,\n        row: int,\n        control_implementation: ControlImplementation,\n        controls: Dict[str, List[str]],\n        component_name: str,\n        parameter_name: str,\n        responsible_roles: List[ResponsibleRole],\n        goal_name_id: str\n    ) -> None:\n\"\"\"Add implemented requirements.\"\"\"\n        goal_remarks = self.xlsx_helper.get_goal_remarks(row)\n        parameter_value_default = self.xlsx_helper.get_parameter_value_default(row)\n        for control in controls.keys():\n            control_uuid = str(uuid.uuid4())\n            prop1 = Property(\n                name='goal_name_id',\n                class_=self._get_class_for_property_name('goal_name_id'),\n                value=goal_name_id,\n                ns=self._get_namespace(),\n                remarks=str(goal_remarks)\n            )\n            prop2 = Property(\n                name='goal_version',\n                class_=self._get_class_for_property_name('goal_version'),\n                value=self._get_goal_version(),\n                ns=self._get_namespace(),\n                remarks=str(goal_name_id)\n            )\n            props = [prop1, prop2]\n            control_id, _ = self.catalog_interface.get_control_id_and_status(control)\n            if not control_id:\n                logger.info(f'row {row} control {control} not found in catalog')\n                control_id = control\n            # implemented_requirement\n            implemented_requirement = ImplementedRequirement(\n                uuid=control_uuid,\n                description=control,\n                props=props,\n                control_id=control_id,\n                responsible_roles=responsible_roles,\n            )\n            # add statements\n            self._add_statements(row, control, controls, component_name, implemented_requirement)\n            # add set_parameter\n            self._add_set_parameter_default(parameter_name, parameter_value_default, implemented_requirement)\n            # implemented_requirements\n            control_implementation.implemented_requirements.append(implemented_requirement)\n\n    def _add_statements(\n        self,\n        row: int,\n        control: str,\n        controls: Dict[str, List[str]],\n        component_name: str,\n        implemented_requirement: ImplementedRequirement\n    ) -> None:\n\"\"\"Add statements.\"\"\"\n        control_statements = controls[control]\n        if control_statements:\n            statements = []\n            for control_statement in control_statements:\n                statement_id = control + control_statement\n                if any(i in control for i in '()'):\n                    control = control.replace('(', '_')\n                    control = control.replace(')', '')\n                    logger.info(f'row {row} control {control} edited to remove parentheses')\n                statement = Statement(\n                    statement_id=control,\n                    uuid=str(uuid.uuid4()),\n                    description=f'{component_name} implements {statement_id}'\n                )\n                statements.append(statement)\n            implemented_requirement.statements = statements\n\n    def _add_set_parameter_values(\n        self, parameter_name: str, parameter_values: str, control_implementation: ControlImplementation\n    ) -> None:\n\"\"\"Add set parameter values (the set of choices).\"\"\"\n        if parameter_name is not None:\n            parameter_name = parameter_name.replace(' ', '_')\n            if parameter_values is not None:\n                set_parameters = [SetParameter(param_id=parameter_name, values=parameter_values)]\n                if control_implementation.set_parameters is None:\n                    control_implementation.set_parameters = []\n                # set_parameters is a list\n                control_implementation.set_parameters.extend(set_parameters)\n\n    def _add_set_parameter_default(\n        self, parameter_name: str, parameter_value_default: str, implemented_requirement: ImplementedRequirement\n    ) -> None:\n\"\"\"Add set parameter default (the \"recommended\" value).\"\"\"\n        if parameter_name is not None:\n            parameter_name = parameter_name.replace(' ', '_')\n            if parameter_value_default is not None:\n                if implemented_requirement.set_parameters is None:\n                    implemented_requirement.set_parameters = []\n                values = [parameter_value_default]\n                set_parameter = SetParameter(param_id=parameter_name, values=values)\n                set_parameters = [set_parameter]\n                # set_parameters is a list\n                implemented_requirement.set_parameters.extend(set_parameters)\n\n    def _get_defined_component(self, component_name: str, component_type: str) -> DefinedComponent:\n\"\"\"Get defined component.\"\"\"\n        key = component_name + key_sep + component_type\n        defined_component = self.defined_components.get(key)\n        if not defined_component:\n            # create new component\n            component_title = component_name\n            component_description = component_name\n            defined_component = DefinedComponent(\n                uuid=str(uuid.uuid4()),\n                description=component_description,\n                title=component_title,\n                type=component_type,\n            )\n            self.defined_components[key] = defined_component\n        return defined_component\n\n    def _build_roles(self) -> List[Role]:\n\"\"\"Build roles.\"\"\"\n        value = [\n            Role(id='prepared-by', title='Indicates the organization that created this content.'),\n            Role(id='prepared-for', title='Indicates the organization for which this content was created..'),\n            Role(\n                id='content-approver',\n                title='Indicates the organization responsible for all content represented in the \"document\".'\n            ),\n        ]\n        return value\n\n    def _build_responsible_roles(self, party_uuid_01: str, party_uuid_02: str,\n                                 party_uuid_03: str) -> List[ResponsibleRole]:\n\"\"\"Build responsible roles.\"\"\"\n        role_prepared_by = ResponsibleRole(role_id='prepared-by', party_uuids=[party_uuid_01])\n        role_prepared_for = ResponsibleRole(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        role_content_approver = ResponsibleRole(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            role_prepared_by,\n            role_prepared_for,\n            role_content_approver,\n        ]\n        return value\n\n    def _build_parties(self, party_uuid_01: str, party_uuid_02: str, party_uuid_03: str) -> List[Party]:\n\"\"\"Build parties.\"\"\"\n        value = [\n            Party(uuid=party_uuid_01, type='organization', name=self._get_org_name(), remarks=self._get_org_remarks()),\n            Party(\n                uuid=party_uuid_02,\n                type='organization',\n                name='Customer',\n                remarks='organization to be customized at account creation only for their Component Definition'\n            ),\n            Party(\n                uuid=party_uuid_03,\n                type='organization',\n                name='ISV',\n                remarks='organization to be customized at ISV subscription only for their Component Definition'\n            ),\n        ]\n        return value\n\n    def _build_responsible_parties(self, party_uuid_01: str, party_uuid_02: str,\n                                   party_uuid_03: str) -> List[ResponsibleParty]:\n\"\"\"Build responsible parties.\"\"\"\n        prepared_by = ResponsibleParty(role_id='prepared-by', party_uuids=[party_uuid_01])\n        prepared_for = ResponsibleParty(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        content_approver = ResponsibleParty(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            prepared_by,\n            prepared_for,\n            content_approver,\n        ]\n        return value\n\n    def _report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n        self.xlsx_helper.report_issues()\n\n    def _get_org_name(self) -> str:\n\"\"\"Get org-name from config.\"\"\"\n        value = self._config.get('org-name')\n        logger.debug(f'org-name: {value}')\n        return value\n\n    def _get_org_remarks(self) -> str:\n\"\"\"Get org-remarks from config.\"\"\"\n        value = self._config.get('org-remarks')\n        logger.debug(f'org-remarks: {value}')\n        return value\n\n    def _get_class_for_property_name(self, property_name: str) -> str:\n\"\"\"Get class for property-name from config.\"\"\"\n        value = None\n        data = self._config.get('property-name-to-class')\n        if data is not None:\n            for item in data.split(','):\n                item = item.strip()\n                parts = item.split(':')\n                if len(parts) != 2 or parts[0] != property_name:\n                    continue\n                value = parts[1]\n                break\n        logger.debug(f'property-name-to-class: {property_name} -> {value}')\n        return value\n\n    def _get_namespace(self) -> str:\n\"\"\"Get namespace from config.\"\"\"\n        value = self._config.get('namespace')\n        logger.debug(f'namespace: {value}')\n        return value\n\n    def _get_catalog_url(self) -> str:\n\"\"\"Get catalog url from config.\"\"\"\n        value = self._config.get('catalog-url')\n        logger.debug(f'catalog-url: {value}')\n        return value\n\n    def _get_catalog_title(self) -> str:\n\"\"\"Get catalog title from config.\"\"\"\n        value = self._config.get('catalog-title')\n        logger.debug(f'catalog-title: {value}')\n        return value\n\n    def _get_goal_version(self) -> str:\n\"\"\"Fix goal_version at 1.0.\"\"\"\n        return '1.0'\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task xlsx-to-oscal-cd.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task xlsx-to-oscal-cd.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self.xlsx_helper = XlsxHelper()\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.execute","title":"execute(self)","text":"

                                    Provide an executed outcome.

                                    Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    self.xlsx_helper.print_info(self.name, 'component_definition')\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.set_timestamp","title":"set_timestamp(self, timestamp)","text":"

                                    Set the timestamp.

                                    Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n    self._timestamp = timestamp\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/","title":"xlsx_to_oscal_profile","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile","title":"trestle.tasks.xlsx_to_oscal_profile","text":"

                                    OSCAL transformation tasks.

                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile","title":" XlsxToOscalProfile (TaskBase) ","text":"

                                    Task to create OSCAL Profile json.

                                    Attributes:

                                    Name Type Description name str

                                    Name of the task.

                                    Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                    class XlsxToOscalProfile(TaskBase):\n\"\"\"\n    Task to create OSCAL Profile json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'xlsx-to-oscal-profile'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task xlsx-to-oscal-profile.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self.xlsx_helper = XlsxHelper()\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n        self._timestamp = timestamp\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        self.xlsx_helper.print_info(self.name, 'profile')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Execute path core.\"\"\"\n        if not self.xlsx_helper.configure(self):\n            return TaskOutcome('failure')\n        # config output\n        odir = self._config.get('output-dir')\n        opth = pathlib.Path(odir)\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'profile.json'\n        ofile = opth / oname\n        if not self._overwrite and pathlib.Path(ofile).exists():\n            logger.error(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # create OSCAL Profile\n        metadata = Metadata(\n            title='Profile for ' + self._get_profile_title(),\n            last_modified=self._timestamp,\n            oscal_version=OSCAL_VERSION,\n            version=get_trestle_version(),\n        )\n        if self.xlsx_helper.profile_type == self.xlsx_helper.by_control:\n            imports = self._get_imports_by_control()\n            profile = Profile(\n                uuid=str(uuid.uuid4()),\n                metadata=metadata,\n                imports=imports,\n            )\n        else:\n            if self.xlsx_helper.profile_type == self.xlsx_helper.by_rule:\n                imports = self._get_imports_by_rule()\n            elif self.xlsx_helper.profile_type == self.xlsx_helper.by_check:\n                imports = self._get_imports_by_check()\n            else:\n                imports = self._get_imports_by_goal()\n            set_parameters = self._get_set_parameters()\n            modify = Modify(set_parameters=set_parameters)\n            profile = Profile(\n                uuid=str(uuid.uuid4()),\n                metadata=metadata,\n                imports=imports,\n                modify=modify,\n            )\n        # write OSCAL Profile to file\n        if self._verbose:\n            logger.info(f'output: {ofile}')\n        profile.oscal_write(pathlib.Path(ofile))\n        # issues\n        self._report_issues()\n        return TaskOutcome('success')\n\n    def _get_imports_by_goal(self) -> List[Import]:\n\"\"\"Get imports by goal.\"\"\"\n        return self._get_imports_by_check()\n\n    def _get_imports_by_control(self) -> List[Import]:\n\"\"\"Get imports by control.\"\"\"\n        import_ = Import(\n            href=self._get_spread_sheet_url(),\n            include_controls=[SelectControlById(with_ids=self._get_with_ids_by_control())],\n        )\n        imports = [import_]\n        return imports\n\n    def _get_imports_by_rule(self) -> List[Import]:\n\"\"\"Get imports by rule.\"\"\"\n        import_ = Import(\n            href=self._get_spread_sheet_url(),\n            include_controls=[SelectControlById(with_ids=self._get_with_ids_by_rule())],\n        )\n        imports = [import_]\n        return imports\n\n    def _get_imports_by_check(self) -> List[Import]:\n\"\"\"Get imports by check.\"\"\"\n        import_ = Import(\n            href=self._get_spread_sheet_url(),\n            include_controls=[SelectControlById(with_ids=self._get_with_ids_by_check())],\n        )\n        imports = [import_]\n        return imports\n\n    def _get_with_ids_by_control(self) -> List[str]:\n\"\"\"Get controls from spread sheet.\"\"\"\n        control_list = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            controls = self.xlsx_helper.get_controls(row)\n            if controls is not None:\n                for control in controls:\n                    control = self._oscal_namify(control)\n                    if control in control_list:\n                        continue\n                    control_list.append(control)\n        return sorted(control_list, key=self._control_sort_key)\n\n    def _get_with_ids_by_rule(self) -> List[str]:\n\"\"\"Get rules from spread sheet.\"\"\"\n        rule_name_id_list = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            rule_name_id = self.xlsx_helper.get_rule_name_id(row, strict=True)\n            if rule_name_id is not None:\n                if rule_name_id in rule_name_id_list:\n                    continue\n                rule_name_id_list.append(rule_name_id)\n        return sorted(rule_name_id_list)\n\n    def _get_with_ids_by_check(self) -> List[str]:\n\"\"\"Get check from spread sheet.\"\"\"\n        check_name_id_list = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            check_name_id = self.xlsx_helper.get_check_name_id(row, strict=True)\n            if check_name_id is not None:\n                if check_name_id in check_name_id_list:\n                    continue\n                check_name_id_list.append(check_name_id)\n        return sorted(check_name_id_list)\n\n    def _control_sort_key(self, control: str) -> Tuple[str, int, int]:\n\"\"\"Fabricate sort key.\"\"\"\n        k1 = control.split('-')[0]\n        k2 = int(control.split('-')[1].split('.')[0])\n        if '.' in control:\n            k3 = int(control.split('-')[1].split('.')[1])\n        else:\n            k3 = 0\n        return (k1, k2, k3)\n\n    def _oscal_namify(self, control: str) -> str:\n\"\"\"Rectify parenthesized numbers in controls.\"\"\"\n        control = control.replace('(', '.')\n        control = control.replace(')', '')\n        return control\n\n    def _get_set_parameters(self) -> List[SetParameter]:\n\"\"\"Get set parameters from spread sheet.\"\"\"\n        set_parameters = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            param_id, label = self.xlsx_helper.get_parameter_name_and_description(row)\n            usage = self.xlsx_helper.get_parameter_usage(row)\n            values = self.xlsx_helper.get_parameter_values(row)\n            if param_id is None:\n                continue\n            set_parameter = SetParameter(\n                param_id=param_id,\n                label=label,\n                usage=usage,\n            )\n            if values is not None:\n                set_parameter.values = values\n            set_parameters.append(set_parameter)\n        return set_parameters\n\n    def _get_profile_title(self) -> str:\n\"\"\"Get profile title from config.\"\"\"\n        value = self._config.get('profile-title')\n        logger.debug(f'profile-title: {value}')\n        return value\n\n    def _get_spread_sheet_url(self) -> str:\n\"\"\"Get spread sheet url from config.\"\"\"\n        value = self._config.get('spread-sheet-url')\n        logger.debug(f'spread-sheet-url: {value}')\n        return value\n\n    def _report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n        self.xlsx_helper.report_issues()\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.__init__","title":"__init__(self, config_object) special","text":"

                                    Initialize trestle task xlsx-to-oscal-profile.

                                    Parameters:

                                    Name Type Description Default config_object Optional[configparser.SectionProxy]

                                    Config section associated with the task.

                                    required Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task xlsx-to-oscal-profile.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self.xlsx_helper = XlsxHelper()\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.execute","title":"execute(self)","text":"

                                    Provide an executed outcome.

                                    Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.print_info","title":"print_info(self)","text":"

                                    Print the help string.

                                    Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    self.xlsx_helper.print_info(self.name, 'profile')\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.set_timestamp","title":"set_timestamp(self, timestamp)","text":"

                                    Set the timestamp.

                                    Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n    self._timestamp = timestamp\n
                                    "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.simulate","title":"simulate(self)","text":"

                                    Provide a simulated outcome.

                                    Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/","title":"osco","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco","title":"trestle.transforms.implementations.osco","text":"

                                    Facilitate OSCAL-OSCO transformation.

                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.logger","title":"logger","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer","title":" OscalProfileToOscoProfileTransformer (FromOscalTransformer) ","text":"

                                    Interface for Oscal Profile to Osco Profile transformer.

                                    Source code in trestle/transforms/implementations/osco.py
                                    class OscalProfileToOscoProfileTransformer(FromOscalTransformer):\n\"\"\"Interface for Oscal Profile to Osco Profile transformer.\"\"\"\n\n    def __init__(\n        self,\n        extends='ocp4-cis-node',\n        api_version='compliance.openshift.io/v1alpha1',\n        kind='TailoredProfile',\n        name='customized-tailored-profile',\n        namespace='openshift-compliance',\n    ) -> None:\n\"\"\"Initialize.\"\"\"\n        self._extends = extends\n        self._api_version = api_version\n        self._kind = kind\n        self._name = name\n        self._namespace = namespace\n\n    def transform(self, profile: Profile) -> str:\n\"\"\"Transform the Profile into a OSCO yaml.\"\"\"\n        self._profile = profile\n        self._osco_version = self._get_normalized_version('osco_version', '0.1.46')\n        # set values\n        set_values = self._get_set_values()\n        # spec\n        if self._osco_version < (0, 1, 40):\n            # for versions prior to 0.1.40, exclude 'description'\n            spec = {\n                'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n                'title': self._profile.metadata.title,\n                'setValues': set_values,\n            }\n        else:\n            # for versions 0.1.40 and beyond, include 'description'\n            spec = {\n                'description': self._get_metadata_prop_value('profile_mnemonic', self._name),\n                'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n                'title': self._profile.metadata.title,\n                'setValues': set_values,\n            }\n        disable_rules = self._get_disable_rules()\n        if disable_rules:\n            spec['disableRules'] = disable_rules\n        # yaml data\n        ydata = {\n            'apiVersion': self._api_version,\n            'kind': self._kind,\n            'metadata': {\n                'name': self._get_metadata_prop_value('profile_mnemonic', self._name),\n                'namespace': self._namespace,\n            },\n            'spec': spec,\n        }\n        return json.dumps(ydata)\n\n    def _get_normalized_version(self, prop_name, prop_default) -> Tuple[int, int, int]:\n\"\"\"Get normalized version.\n\n        Normalize the \"x.y.z\" string value to an integer: 1,000,000*x + 1,000*y + z.\n        \"\"\"\n        try:\n            vparts = self._get_metadata_prop_value(prop_name, prop_default).split('.')\n            normalized_version = (int(vparts[0]), int(vparts[1]), int(vparts[2]))\n        except Exception:\n            logger.warning(f'metadata prop name={prop_name} value error')\n            vparts = prop_default.split('.')\n            normalized_version = (int(vparts[0]), int(vparts[1]), int(vparts[2]))\n        return normalized_version\n\n    def _get_set_values(self) -> List[Dict]:\n\"\"\"Extract set_paramater name/value pairs from profile.\"\"\"\n        set_values = []\n        # for check versions prior to 0.1.59 include parameters\n        # for later versions parameters should not be specified, caveat emptor\n        if self._profile.modify is not None:\n            for set_parameter in as_list(self._profile.modify.set_parameters):\n                name = self._format_osco_rule_name(set_parameter.param_id)\n                parameter_value = set_parameter.values[0]\n                value = parameter_value\n                rationale = self._get_rationale_for_set_value()\n                set_value = {'name': name, 'value': value, 'rationale': rationale}\n                set_values.append(set_value)\n        return set_values\n\n    def _format_osco_rule_name(self, name: str) -> str:\n\"\"\"Format for OSCO.\n\n        1. remove prefix xccdf_org.ssgproject.content_rule_\n        2. change underscores to dashes\n        3. add prefix ocp4-\n        \"\"\"\n        normalized_name = name.replace('xccdf_org.ssgproject.content_rule_', '').replace('_', '-')\n        if not normalized_name.startswith('ocp4-'):\n            normalized_name = f'ocp4-{normalized_name}'\n        return normalized_name\n\n    def _get_metadata_prop_value(self, name: str, default_: str) -> str:\n\"\"\"Extract metadata prop or else default if not present.\"\"\"\n        for prop in as_list(self._profile.metadata.props):\n            if prop.name == name:\n                return prop.value\n        logger.info(f'using default: {name} = {default_}')\n        return default_\n\n    def _get_disable_rules(self) -> List[str]:\n\"\"\"Extract disabled rules.\"\"\"\n        value = []\n        for _import in as_list(self._profile.imports):\n            for control in as_list(_import.exclude_controls):\n                self._add_disable_rules_for_control(value, control)\n        return value\n\n    def _add_disable_rules_for_control(self, value, control):\n\"\"\"Extract disabled rules for control.\"\"\"\n        for with_id in as_list(control.with_ids):\n            name = self._format_osco_rule_name(with_id.__root__)\n            rationale = self._get_rationale_for_disable_rule()\n            entry = {'name': name, 'rationale': rationale}\n            value.append(entry)\n\n    def _get_rationale_for_set_value(self) -> str:\n\"\"\"Rationale for set value.\"\"\"\n        return 'not determinable from specification'\n\n    def _get_rationale_for_disable_rule(self) -> str:\n\"\"\"Rationale for disable rule.\"\"\"\n        return 'not determinable from specification'\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer.__init__","title":"__init__(self, extends='ocp4-cis-node', api_version='compliance.openshift.io/v1alpha1', kind='TailoredProfile', name='customized-tailored-profile', namespace='openshift-compliance') special","text":"

                                    Initialize.

                                    Source code in trestle/transforms/implementations/osco.py
                                    def __init__(\n    self,\n    extends='ocp4-cis-node',\n    api_version='compliance.openshift.io/v1alpha1',\n    kind='TailoredProfile',\n    name='customized-tailored-profile',\n    namespace='openshift-compliance',\n) -> None:\n\"\"\"Initialize.\"\"\"\n    self._extends = extends\n    self._api_version = api_version\n    self._kind = kind\n    self._name = name\n    self._namespace = namespace\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer.transform","title":"transform(self, profile)","text":"

                                    Transform the Profile into a OSCO yaml.

                                    Source code in trestle/transforms/implementations/osco.py
                                    def transform(self, profile: Profile) -> str:\n\"\"\"Transform the Profile into a OSCO yaml.\"\"\"\n    self._profile = profile\n    self._osco_version = self._get_normalized_version('osco_version', '0.1.46')\n    # set values\n    set_values = self._get_set_values()\n    # spec\n    if self._osco_version < (0, 1, 40):\n        # for versions prior to 0.1.40, exclude 'description'\n        spec = {\n            'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n            'title': self._profile.metadata.title,\n            'setValues': set_values,\n        }\n    else:\n        # for versions 0.1.40 and beyond, include 'description'\n        spec = {\n            'description': self._get_metadata_prop_value('profile_mnemonic', self._name),\n            'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n            'title': self._profile.metadata.title,\n            'setValues': set_values,\n        }\n    disable_rules = self._get_disable_rules()\n    if disable_rules:\n        spec['disableRules'] = disable_rules\n    # yaml data\n    ydata = {\n        'apiVersion': self._api_version,\n        'kind': self._kind,\n        'metadata': {\n            'name': self._get_metadata_prop_value('profile_mnemonic', self._name),\n            'namespace': self._namespace,\n        },\n        'spec': spec,\n    }\n    return json.dumps(ydata)\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer","title":" OscoResultToOscalARTransformer (ResultsTransformer) ","text":"

                                    Interface for Osco transformer.

                                    Source code in trestle/transforms/implementations/osco.py
                                    class OscoResultToOscalARTransformer(ResultsTransformer):\n\"\"\"Interface for Osco transformer.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._modes = {}\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"Analysis.\"\"\"\n        return self._results_factory.analysis\n\n    @property\n    def checking(self):\n\"\"\"Return checking.\"\"\"\n        return self._modes.get('checking', False)\n\n    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n        if modes is not None:\n            self._modes = modes\n\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n        The expected blob is a string that is one of:\n            - data from OpenShift Compliance Operator (json, yaml, xml)\n            - data from Auditree OSCO fetcher/check (json)\n        \"\"\"\n        results = None\n        self._results_factory = _OscalResultsFactory(self.get_timestamp(), self.checking)\n        if results is None:\n            results = self._ingest_xml(blob)\n        if results is None:\n            results = self._ingest_json(blob)\n        if results is None:\n            results = self._ingest_yaml(blob)\n        return results\n\n    def _ingest_xml(self, blob: str) -> Results:\n\"\"\"Ingest xml data.\"\"\"\n        # ?xml data\n        if blob.startswith('<?xml'):\n            resource = blob\n            self._results_factory.ingest_xml(resource)\n        else:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_json(self, blob: str) -> Results:\n\"\"\"Ingest json data.\"\"\"\n        try:\n            # ? configmaps or auditree data\n            jdata = json.loads(blob)\n            # https://docs.openshift.com/container-platform/3.7/rest_api/api/v1.ConfigMap.html#Get-api-v1-namespaces-namespace-configmaps-name\n            if 'kind' in jdata.keys() and jdata['kind'] == 'ConfigMapList' and 'items' in jdata.keys():\n                items = jdata['items']\n                for item in items:\n                    if 'data' in item.keys():\n                        data = item['data']\n                        if 'results' in data:\n                            resource = item\n                            self._results_factory.ingest(resource)\n            # https://github.com/ComplianceAsCode/auditree-arboretum/blob/main/arboretum/kubernetes/fetchers/fetch_cluster_resource.py\n            else:\n                for key in jdata.keys():\n                    for group in jdata[key]:\n                        for cluster in jdata[key][group]:\n                            if 'resources' in cluster:\n                                for resource in cluster['resources']:\n                                    self._results_factory.ingest(resource)\n        except json.decoder.JSONDecodeError:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_yaml(self, blob: str) -> Results:\n\"\"\"Ingest yaml data.\"\"\"\n        try:\n            # ? yaml data\n            yaml = YAML(typ='safe')\n            resource = yaml.load(blob)\n            self._results_factory.ingest(resource)\n        except Exception as e:\n            raise e\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.analysis","title":"analysis: List[str] property readonly","text":"

                                    Analysis.

                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.checking","title":"checking property readonly","text":"

                                    Return checking.

                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.__init__","title":"__init__(self) special","text":"

                                    Initialize.

                                    Source code in trestle/transforms/implementations/osco.py
                                    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._modes = {}\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.set_modes","title":"set_modes(self, modes)","text":"

                                    Keep modes info.

                                    Source code in trestle/transforms/implementations/osco.py
                                    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n    if modes is not None:\n        self._modes = modes\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.transform","title":"transform(self, blob)","text":"

                                    Transform the blob into a Results.

                                    The expected blob is a string that is one of: - data from OpenShift Compliance Operator (json, yaml, xml) - data from Auditree OSCO fetcher/check (json)

                                    Source code in trestle/transforms/implementations/osco.py
                                    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n    The expected blob is a string that is one of:\n        - data from OpenShift Compliance Operator (json, yaml, xml)\n        - data from Auditree OSCO fetcher/check (json)\n    \"\"\"\n    results = None\n    self._results_factory = _OscalResultsFactory(self.get_timestamp(), self.checking)\n    if results is None:\n        results = self._ingest_xml(blob)\n    if results is None:\n        results = self._ingest_json(blob)\n    if results is None:\n        results = self._ingest_yaml(blob)\n    return results\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoTransformer","title":" OscoTransformer (OscoResultToOscalARTransformer) ","text":"

                                    Legacy class name.

                                    Source code in trestle/transforms/implementations/osco.py
                                    class OscoTransformer(OscoResultToOscalARTransformer):\n\"\"\"Legacy class name.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse","title":" RuleUse ","text":"

                                    Represents one rule of OSCO data.

                                    Source code in trestle/transforms/implementations/osco.py
                                    class RuleUse():\n\"\"\"Represents one rule of OSCO data.\"\"\"\n\n    def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self.id_ = args['id_']\n        self.target = args['target']\n        self.target_type = args['target_type']\n        self.host_name = args['host_name']\n        self.benchmark_href = args['benchmark_href']\n        self.benchmark_id = args['benchmark_id']\n        self.scanner_name = args['scanner_name']\n        self.scanner_version = args['scanner_version']\n        self.idref = args['idref']\n        self.version = args['version']\n        self.time = args['time']\n        self.result = args['result']\n        self.severity = args['severity']\n        self.weight = args['weight']\n\n    @property\n    def inventory_key(self):\n\"\"\"Derive inventory key.\"\"\"\n        if self.host_name is None:\n            # OpenScap 1.3.3\n            rval = self.target + ':' + self.target_type\n        else:\n            # OpenScap 1.3.5\n            rval = self.host_name + ':' + self.target_type\n        return rval\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse.inventory_key","title":"inventory_key property readonly","text":"

                                    Derive inventory key.

                                    "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse.__init__","title":"__init__(self, args) special","text":"

                                    Initialize given specified args.

                                    Source code in trestle/transforms/implementations/osco.py
                                    def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self.id_ = args['id_']\n    self.target = args['target']\n    self.target_type = args['target_type']\n    self.host_name = args['host_name']\n    self.benchmark_href = args['benchmark_href']\n    self.benchmark_id = args['benchmark_id']\n    self.scanner_name = args['scanner_name']\n    self.scanner_version = args['scanner_version']\n    self.idref = args['idref']\n    self.version = args['version']\n    self.time = args['time']\n    self.result = args['result']\n    self.severity = args['severity']\n    self.weight = args['weight']\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/","title":"tanium","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium","title":"trestle.transforms.implementations.tanium","text":"

                                    Facilitate Tanium result to NIST OSCAL transformation.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.logger","title":"logger","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUse","title":" RuleUse ","text":"

                                    Represents one row of Tanium data.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    class RuleUse():\n\"\"\"Represents one row of Tanium data.\"\"\"\n\n    def __init__(self, tanium_row: Dict[str, Any], comply: Dict[str, str], default_timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        logger.debug(f'tanium-row: {tanium_row}')\n        try:\n            # level 1 keys\n            self.computer_name = tanium_row['Computer Name']\n            self.tanium_client_ip_address = tanium_row['Tanium Client IP Address']\n            self.ip_address = str(tanium_row['IP Address'])\n            self.count = str(tanium_row['Count'])\n            # comply keys\n            self.check_id = comply['Check ID']\n            self.rule_id = comply['Rule ID']\n            self.state = comply['State']\n            # defaults\n            no_results = '[no results]'\n            self.check_id_level = no_results\n            self.check_id_version = no_results\n            self.check_id_benchmark = no_results\n            self.component = no_results\n            self.component_type = no_results\n            # parse\n            if ';' in self.check_id:\n                items = self.check_id.split(';')\n                if len(items) > 2:\n                    self.check_id_level = items[2]\n                if len(items) > 1:\n                    self.check_id_version = items[1]\n                if len(items) > 0:\n                    self.check_id_benchmark = items[0]\n                    self.component = items[0]\n                    if self.component.startswith('CIS '):\n                        self.component = self.component[len('CIS '):]\n                    if self.component.endswith(' Benchmark'):\n                        self.component = self.component[:-len(' Benchmark')]\n                    self.component_type = 'Operating System'\n            # timestamp\n            self.timestamp = comply.get('Timestamp', default_timestamp)\n            # collected\n            self.collected = default_timestamp\n        except Exception as e:\n            logger.debug(f'tanium-row: {tanium_row}')\n            logger.debug(e)\n            logger.debug(traceback.format_exc())\n            raise e\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUse-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUse.__init__","title":"__init__(self, tanium_row, comply, default_timestamp) special","text":"

                                    Initialize given specified args.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    def __init__(self, tanium_row: Dict[str, Any], comply: Dict[str, str], default_timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    logger.debug(f'tanium-row: {tanium_row}')\n    try:\n        # level 1 keys\n        self.computer_name = tanium_row['Computer Name']\n        self.tanium_client_ip_address = tanium_row['Tanium Client IP Address']\n        self.ip_address = str(tanium_row['IP Address'])\n        self.count = str(tanium_row['Count'])\n        # comply keys\n        self.check_id = comply['Check ID']\n        self.rule_id = comply['Rule ID']\n        self.state = comply['State']\n        # defaults\n        no_results = '[no results]'\n        self.check_id_level = no_results\n        self.check_id_version = no_results\n        self.check_id_benchmark = no_results\n        self.component = no_results\n        self.component_type = no_results\n        # parse\n        if ';' in self.check_id:\n            items = self.check_id.split(';')\n            if len(items) > 2:\n                self.check_id_level = items[2]\n            if len(items) > 1:\n                self.check_id_version = items[1]\n            if len(items) > 0:\n                self.check_id_benchmark = items[0]\n                self.component = items[0]\n                if self.component.startswith('CIS '):\n                    self.component = self.component[len('CIS '):]\n                if self.component.endswith(' Benchmark'):\n                    self.component = self.component[:-len(' Benchmark')]\n                self.component_type = 'Operating System'\n        # timestamp\n        self.timestamp = comply.get('Timestamp', default_timestamp)\n        # collected\n        self.collected = default_timestamp\n    except Exception as e:\n        logger.debug(f'tanium-row: {tanium_row}')\n        logger.debug(e)\n        logger.debug(traceback.format_exc())\n        raise e\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory","title":" RuleUseFactory ","text":"

                                    Build RuleUse list.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    class RuleUseFactory():\n\"\"\"Build RuleUse list.\"\"\"\n\n    def __init__(self, timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self._timestamp = timestamp\n\n    def _make_sublist(self, tanium_row: Dict[str, Any]) -> List[RuleUse]:\n\"\"\"Build RuleUse sublist from input data item.\"\"\"\n        retval = []\n        keys = tanium_row\n        for key in keys:\n            if key.startswith('Comply'):\n                break\n        comply_list = tanium_row[key]\n        for comply in comply_list:\n            rule_use = RuleUse(tanium_row, comply, self._timestamp)\n            retval.append(rule_use)\n        return retval\n\n    def make_list(self, blob: str) -> List[RuleUse]:\n\"\"\"Build RuleUse list from input data.\"\"\"\n        retval = []\n        lines = blob.splitlines()\n        for line in lines:\n            line = line.strip()\n            if line:\n                jdata = json.loads(line)\n                if type(jdata) is list:\n                    for item in jdata:\n                        logger.debug(f'item: {item}')\n                        retval += self._make_sublist(item)\n                else:\n                    logger.debug(f'jdata: {jdata}')\n                    retval += self._make_sublist(jdata)\n        logger.debug(f'ru_list: {len(retval)}')\n        return retval\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory.__init__","title":"__init__(self, timestamp) special","text":"

                                    Initialize given specified args.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    def __init__(self, timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self._timestamp = timestamp\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory.make_list","title":"make_list(self, blob)","text":"

                                    Build RuleUse list from input data.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    def make_list(self, blob: str) -> List[RuleUse]:\n\"\"\"Build RuleUse list from input data.\"\"\"\n    retval = []\n    lines = blob.splitlines()\n    for line in lines:\n        line = line.strip()\n        if line:\n            jdata = json.loads(line)\n            if type(jdata) is list:\n                for item in jdata:\n                    logger.debug(f'item: {item}')\n                    retval += self._make_sublist(item)\n            else:\n                logger.debug(f'jdata: {jdata}')\n                retval += self._make_sublist(jdata)\n    logger.debug(f'ru_list: {len(retval)}')\n    return retval\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory","title":" TaniumOscalFactory ","text":"

                                    Build Tanium OSCAL entities.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    class TaniumOscalFactory():\n\"\"\"Build Tanium OSCAL entities.\"\"\"\n\n    def __init__(\n        self,\n        timestamp: str,\n        rule_use_list: List[RuleUse],\n        blocksize: int = 11000,\n        cpus_max: int = 1,\n        cpus_min: int = 1,\n        checking: bool = False,\n        caching: bool = True,\n        aggregate: bool = True\n    ) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self._rule_use_list = rule_use_list\n        self._timestamp = timestamp\n        self._component_map: Dict[str, SystemComponent] = {}\n        self._inventory_map: Dict[str, InventoryItem] = {}\n        self._observation_list: List[Observation] = []\n        self._ns = 'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium'\n        self._cpus = None\n        self._checking = checking\n        self._caching = caching\n        self._aggregate = aggregate\n        self._result = None\n        # blocksize: default, min\n        self._blocksize = blocksize\n        if self._blocksize < 1:\n            self._blocksize = 1\n        # cpus max: default, max, min\n        self._cpus_max = cpus_max\n        if self._cpus_max > os.cpu_count():\n            self._cpus_max = os.cpu_count()\n        self._cpus_min = cpus_min\n        if self._cpus_min > self._cpus_max:\n            self._cpus_min = self._cpus_max\n        if self._cpus_min < 1:\n            self._cpus_min = 1\n        self._property_accounting = PropertyAccounting()\n        self._property_manager = PropertyManager(caching=caching, checking=checking)\n\n    def _is_duplicate_component(self, rule_use: RuleUse) -> bool:\n\"\"\"Check for duplicate component.\"\"\"\n        retval = False\n        component_type = rule_use.component_type\n        component_title = rule_use.component\n        for component in self._component_map.values():\n            if component.type != component_type:\n                continue\n            if component.title != component_title:\n                continue\n            retval = True\n            break\n        return retval\n\n    def _derive_components(self) -> None:\n\"\"\"Derive components from RuleUse list.\"\"\"\n        self._component_map: Dict[str, SystemComponent] = {}\n        for rule_use in self._rule_use_list:\n            if self._is_duplicate_component(rule_use):\n                continue\n            component_type = rule_use.component_type\n            component_title = rule_use.component\n            # See Note in _get_component_ref.\n            component_description = rule_use.component\n            component_ref = _uuid_component()\n            status = Status(state='operational')\n            component = SystemComponent(\n                uuid=component_ref,\n                type=component_type,\n                title=component_title,\n                description=component_description,\n                status=status\n            )\n            self._component_map[component_ref] = component\n\n    def _get_component_ref(self, rule_use: RuleUse) -> Optional[str]:\n\"\"\"Get component reference for specified rule use.\"\"\"\n        uuid = None\n        for component_ref, component in self._component_map.items():\n            if component.type != rule_use.component_type:\n                continue\n            if component.title != rule_use.component:\n                continue\n            # Note: currently title and description are the same,\n            # therefore checking description is not necessary.\n            uuid = component_ref\n            break\n        return uuid\n\n    def _derive_inventory(self) -> None:\n\"\"\"Derive inventory from RuleUse list.\"\"\"\n        self._inventory_map: Dict[str, InventoryItem] = {}\n        for rule_use in self._rule_use_list:\n            if rule_use.tanium_client_ip_address in self._inventory_map:\n                continue\n            inventory = InventoryItem(uuid=_uuid_inventory(), description='inventory')\n            inventory.props = [\n                self._property_manager.materialize(name='Computer_Name', value=rule_use.computer_name, ns=self._ns),\n                self._property_manager.materialize(\n                    name='Tanium_Client_IP_Address',\n                    value=rule_use.tanium_client_ip_address,\n                    ns=self._ns,\n                    class_='scc_inventory_item_id'\n                ),\n                self._property_manager.materialize(name='IP_Address', value=rule_use.ip_address, ns=self._ns),\n                self._property_manager.materialize(name='Count', value=rule_use.count, ns=self._ns)\n            ]\n            component_uuid = self._get_component_ref(rule_use)\n            if component_uuid is not None:\n                inventory.implemented_components = [ImplementedComponent(component_uuid=component_uuid)]\n            self._inventory_map[rule_use.tanium_client_ip_address] = inventory\n\n    def _get_inventory_ref(self, rule_use: RuleUse) -> str:\n\"\"\"Get inventory reference for specified rule use.\"\"\"\n        return self._inventory_map[rule_use.tanium_client_ip_address].uuid\n\n    def _conditional_include(\n        self,\n        props: List[Property],\n        group: str = None,\n        name: str = None,\n        value: str = None,\n        ns: str = None,\n        class_: str = None\n    ) -> None:\n\"\"\"Add non-aggregated property or remember common property.\"\"\"\n        if self._aggregate:\n            if self._property_accounting.is_common_property(group=group, name=name, value=value, ns=ns, class_=class_):\n                # common property\n                self._property_manager.put_common_property(group=group, name=name, value=value, ns=ns, class_=class_)\n                return\n        # non-aggregated property\n        props.append(self._property_manager.materialize(name=name, value=value, ns=ns, class_=class_))\n\n    def _get_observtion_properties(self, rule_use: RuleUse) -> List[Property]:\n\"\"\"Get observation properties.\"\"\"\n        props = []\n        group = self._get_component_ref(rule_use)\n        self._conditional_include(props=props, group=group, name='Check_ID', value=rule_use.check_id, ns=self._ns)\n        self._conditional_include(\n            props=props,\n            group=group,\n            name='Check_ID_Benchmark',\n            value=rule_use.check_id_benchmark,\n            ns=self._ns,\n            class_='scc_predefined_profile'\n        )\n        self._conditional_include(\n            props=props,\n            group=group,\n            name='Check_ID_Version',\n            value=rule_use.check_id_version,\n            ns=self._ns,\n            class_='scc_predefined_profile_version'\n        )\n        self._conditional_include(\n            props=props, group=group, name='Check_ID_Level', value=rule_use.check_id_level, ns=self._ns\n        )\n        self._conditional_include(\n            props=props,\n            group=group,\n            name='Rule_ID',\n            value=rule_use.rule_id,\n            ns=self._ns,\n            class_='scc_goal_description'\n        )\n        self._conditional_include(\n            props=props, group=group, name='Rule_ID', value=rule_use.rule_id, ns=self._ns, class_='scc_check_name_id'\n        )\n        self._conditional_include(\n            props=props, group=group, name='State', value=rule_use.state, ns=self._ns, class_='scc_result'\n        )\n        self._conditional_include(\n            props=props, group=group, name='Timestamp', value=rule_use.timestamp, ns=self._ns, class_='scc_timestamp'\n        )\n        return props\n\n    def _derive_common_property_accounting(self) -> None:\n\"\"\"Derive common properties accounting from RuleUse list.\"\"\"\n        for rule_use in self._rule_use_list:\n            group = self._get_component_ref(rule_use)\n            self._property_accounting.count_group(group=group)\n            self._property_accounting.count_property(group=group, name='Check_ID', value=rule_use.check_id, ns=self._ns)\n            self._property_accounting.count_property(\n                group=group,\n                name='Check_ID_Benchmark',\n                value=rule_use.check_id_benchmark,\n                ns=self._ns,\n                class_='scc_predefined_profile'\n            )\n            self._property_accounting.count_property(\n                group=group,\n                name='Check_ID_Version',\n                value=rule_use.check_id_version,\n                ns=self._ns,\n                class_='scc_predefined_profile_version'\n            )\n            self._property_accounting.count_property(\n                group=group, name='Check_ID_Level', value=rule_use.check_id_level, ns=self._ns\n            )\n            self._property_accounting.count_property(\n                group=group, name='Rule_ID', value=rule_use.rule_id, ns=self._ns, class_='scc_goal_description'\n            )\n            self._property_accounting.count_property(\n                group=group, name='Rule_ID', value=rule_use.rule_id, ns=self._ns, class_='scc_check_name_id'\n            )\n            self._property_accounting.count_property(\n                group=group, name='State', value=rule_use.state, ns=self._ns, class_='scc_result'\n            )\n            self._property_accounting.count_property(\n                group=group, name='Timestamp', value=rule_use.timestamp, ns=self._ns, class_='scc_timestamp'\n            )\n\n    # parallel process to process one chuck of entire data set\n    def _batch_observations(self, index: int) -> Dict[str, List[Observation]]:\n\"\"\"Derive batch of observations from RuleUse list.\"\"\"\n        observation_partial_map: Dict[str, List[Observation]] = {}\n        # determine which chunk to process\n        batch_size = (len(self._rule_use_list) // self._batch_workers) + 1\n        start = index * batch_size\n        end = (index + 1) * batch_size\n        end = min(end, len(self._rule_use_list))\n        logger.debug(f'start: {start} end: {end-1}')\n        # process just the one chunk\n        for i in range(start, end):\n            rule_use = self._rule_use_list[i]\n            observation = Observation(\n                uuid=_uuid_observation(),\n                description=rule_use.rule_id,\n                methods=['TEST-AUTOMATED'],\n                collected=rule_use.collected\n            )\n            subject_uuid = self._get_inventory_ref(rule_use)\n            subject_reference = SubjectReference(subject_uuid=subject_uuid, type='inventory-item')\n            observation.subjects = [subject_reference]\n            observation.props = self._get_observtion_properties(rule_use)\n            observation_partial_map[subject_uuid] = observation_partial_map.get(subject_uuid, []) + [observation]\n        return observation_partial_map\n\n    @property\n    def _batch_workers(self) -> int:\n\"\"\"Calculate number of parallel processes to employ.\"\"\"\n        if self._cpus is None:\n            cpus_estimate = len(self._rule_use_list) // self._blocksize\n            self._cpus = max(min(cpus_estimate, self._cpus_max), self._cpus_min)\n            logger.debug(f'CPUs estimate: {cpus_estimate} available: {os.cpu_count()} selection: {self._cpus}')\n        return self._cpus\n\n    def _derive_observations(self) -> None:\n\"\"\"Derive observations from RuleUse list.\"\"\"\n        self._observation_map = {}\n        if self._batch_workers == 1:\n            # no need for multiprocessing\n            self._observation_map = self._batch_observations(0)\n        else:\n            # use multiprocessing to perform observations creation in parallel\n            pool = multiprocessing.Pool(processes=self._batch_workers)\n            rval_list = pool.map(self._batch_observations, range(self._batch_workers))\n            # gather observations from the sundry batch workers\n            for partial_observation_map in rval_list:\n                self._observation_map = join_key_to_list_dicts(self._observation_map, partial_observation_map)\n\n    @property\n    def components(self) -> List[SystemComponent]:\n\"\"\"OSCAL components.\"\"\"\n        return list(self._component_map.values())\n\n    @property\n    def inventory(self) -> ValuesView[InventoryItem]:\n\"\"\"OSCAL inventory.\"\"\"\n        return self._inventory_map.values()\n\n    @property\n    def observations(self) -> List[Observation]:\n\"\"\"OSCAL observations.\"\"\"\n        rval = []\n        # observations are partitioned by local-definition uuid; join them into one list\n        for key in self._observation_map:\n            list_ = self._observation_map[key]\n            for observation in list_:\n                rval.append(observation)\n        return rval\n\n    @property\n    def control_selections(self) -> List[ControlSelection]:\n\"\"\"OSCAL control selections.\"\"\"\n        rval = []\n        rval.append(ControlSelection())\n        return rval\n\n    @property\n    def reviewed_controls(self) -> ReviewedControls:\n\"\"\"OSCAL reviewed controls.\"\"\"\n        rval = ReviewedControls(control_selections=self.control_selections)\n        return rval\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"OSCAL statistics.\"\"\"\n        analysis = []\n        analysis.append(f'components: {len(self.components)}')\n        analysis.append(f'inventory: {len(self.inventory)}')\n        analysis.append(f'observations: {len(self.observations)}')\n        analysis.append(f'cache: requests={self._property_manager.requests} hits={self._property_manager.hits}')\n        return analysis\n\n    def _get_local_definitions(self, system_component: SystemComponent) -> LocalDefinitions1:\n\"\"\"Get local definitions.\"\"\"\n        rval = LocalDefinitions1()\n        for component in self.components:\n            if component.uuid == system_component.uuid:\n                rval.components = [component]\n                rval.inventory_items = []\n                for inventory_item in self.inventory:\n                    for implemented_component in inventory_item.implemented_components:\n                        if implemented_component.component_uuid == system_component.uuid:\n                            rval.inventory_items.append(inventory_item)\n                break\n        return rval\n\n    def _get_local_definitions_uuids(self, local_definitions: LocalDefinitions1) -> List[str]:\n\"\"\"Get inventory uuids for given local definitions.\"\"\"\n        rval = []\n        if local_definitions.inventory_items:\n            rval = [inventory_item.uuid for inventory_item in local_definitions.inventory_items]\n        return rval\n\n    def _get_observations_for_uuid(self, uuid_: str) -> List[Observation]:\n\"\"\"Get observations for given uuid.\"\"\"\n        rval = 0\n        if uuid_ in self._observation_map:\n            rval = []\n            list_ = self._observation_map[uuid_]\n            for observation in list_:\n                rval.append(observation)\n        return rval\n\n    def _get_observations(self, local_definitions: LocalDefinitions1) -> List[Observation]:\n\"\"\"Get observations for given local definitions.\"\"\"\n        rval = []\n        local_definitions_uuids = self._get_local_definitions_uuids(local_definitions)\n        for uuid_ in local_definitions_uuids:\n            observations = self._get_observations_for_uuid(uuid_)\n            if observations:\n                rval += observations\n        return rval\n\n    def _get_properties(self, group: str) -> List[Property]:\n\"\"\"Get properties for given group.\"\"\"\n        return self._property_manager.get_common_properties(group)\n\n    @property\n    def results(self) -> List[Result]:\n\"\"\"OSCAL result.\"\"\"\n        if self._result is None:\n            self._derive_components()\n            self._derive_inventory()\n            if self._aggregate:\n                self._derive_common_property_accounting()\n            self._derive_observations()\n        results = []\n        for component in self.components:\n            local_definitions = self._get_local_definitions(component)\n            observations = self._get_observations(local_definitions)\n            result = Result(\n                uuid=_uuid_result(),\n                title='Tanium',\n                description='Tanium',\n                start=self._timestamp,\n                end=self._timestamp,\n                reviewed_controls=self.reviewed_controls,\n                local_definitions=local_definitions,\n                observations=observations\n            )\n            component_ref = component.uuid\n            result.props = self._get_properties(component_ref)\n            results.append(result)\n        return results\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.analysis","title":"analysis: List[str] property readonly","text":"

                                    OSCAL statistics.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.components","title":"components: List[trestle.oscal.common.SystemComponent] property readonly","text":"

                                    OSCAL components.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.control_selections","title":"control_selections: List[trestle.oscal.common.ControlSelection] property readonly","text":"

                                    OSCAL control selections.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.inventory","title":"inventory: ValuesView[trestle.oscal.common.InventoryItem] property readonly","text":"

                                    OSCAL inventory.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.observations","title":"observations: List[trestle.oscal.common.Observation] property readonly","text":"

                                    OSCAL observations.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.results","title":"results: List[trestle.oscal.assessment_results.Result] property readonly","text":"

                                    OSCAL result.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.reviewed_controls","title":"reviewed_controls: ReviewedControls property readonly","text":"

                                    OSCAL reviewed controls.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.__init__","title":"__init__(self, timestamp, rule_use_list, blocksize=11000, cpus_max=1, cpus_min=1, checking=False, caching=True, aggregate=True) special","text":"

                                    Initialize given specified args.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    def __init__(\n    self,\n    timestamp: str,\n    rule_use_list: List[RuleUse],\n    blocksize: int = 11000,\n    cpus_max: int = 1,\n    cpus_min: int = 1,\n    checking: bool = False,\n    caching: bool = True,\n    aggregate: bool = True\n) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self._rule_use_list = rule_use_list\n    self._timestamp = timestamp\n    self._component_map: Dict[str, SystemComponent] = {}\n    self._inventory_map: Dict[str, InventoryItem] = {}\n    self._observation_list: List[Observation] = []\n    self._ns = 'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium'\n    self._cpus = None\n    self._checking = checking\n    self._caching = caching\n    self._aggregate = aggregate\n    self._result = None\n    # blocksize: default, min\n    self._blocksize = blocksize\n    if self._blocksize < 1:\n        self._blocksize = 1\n    # cpus max: default, max, min\n    self._cpus_max = cpus_max\n    if self._cpus_max > os.cpu_count():\n        self._cpus_max = os.cpu_count()\n    self._cpus_min = cpus_min\n    if self._cpus_min > self._cpus_max:\n        self._cpus_min = self._cpus_max\n    if self._cpus_min < 1:\n        self._cpus_min = 1\n    self._property_accounting = PropertyAccounting()\n    self._property_manager = PropertyManager(caching=caching, checking=checking)\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer","title":" TaniumResultToOscalARTransformer (ResultsTransformer) ","text":"

                                    Interface for Tanium transformer.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    class TaniumResultToOscalARTransformer(ResultsTransformer):\n\"\"\"Interface for Tanium transformer.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._modes = {}\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"Return analysis info.\"\"\"\n        return self._analysis\n\n    @property\n    def blocksize(self) -> int:\n\"\"\"Return blocksize.\"\"\"\n        return self._modes.get('blocksize', 10000)\n\n    @property\n    def cpus_max(self) -> int:\n\"\"\"Return cpus_max.\"\"\"\n        return self._modes.get('cpus_max', 1)\n\n    @property\n    def cpus_min(self) -> int:\n\"\"\"Return cpus_min.\"\"\"\n        return self._modes.get('cpus_min', 1)\n\n    @property\n    def aggregate(self) -> bool:\n\"\"\"Return aggregate.\"\"\"\n        return self._modes.get('aggregate', True)\n\n    @property\n    def caching(self) -> bool:\n\"\"\"Return caching.\"\"\"\n        return self._modes.get('caching', True)\n\n    @property\n    def checking(self) -> bool:\n\"\"\"Return checking.\"\"\"\n        return self._modes.get('checking', False)\n\n    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n        if modes is not None:\n            self._modes = modes\n\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\"\"\"\n        ts0 = datetime.datetime.now()\n        results = Results()\n        ru_factory = RuleUseFactory(self.get_timestamp())\n        ru_list = ru_factory.make_list(blob)\n        tanium_oscal_factory = TaniumOscalFactory(\n            self.get_timestamp(),\n            ru_list,\n            self.blocksize,\n            self.cpus_max,\n            self.cpus_min,\n            self.checking,\n            self.caching,\n            self.aggregate\n        )\n        results.__root__ = tanium_oscal_factory.results\n        ts1 = datetime.datetime.now()\n        self._analysis = tanium_oscal_factory.analysis\n        self._analysis.append(f'transform time: {ts1-ts0}')\n        return results\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.aggregate","title":"aggregate: bool property readonly","text":"

                                    Return aggregate.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.analysis","title":"analysis: List[str] property readonly","text":"

                                    Return analysis info.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.blocksize","title":"blocksize: int property readonly","text":"

                                    Return blocksize.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.caching","title":"caching: bool property readonly","text":"

                                    Return caching.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.checking","title":"checking: bool property readonly","text":"

                                    Return checking.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.cpus_max","title":"cpus_max: int property readonly","text":"

                                    Return cpus_max.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.cpus_min","title":"cpus_min: int property readonly","text":"

                                    Return cpus_min.

                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.__init__","title":"__init__(self) special","text":"

                                    Initialize.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._modes = {}\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.set_modes","title":"set_modes(self, modes)","text":"

                                    Keep modes info.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n    if modes is not None:\n        self._modes = modes\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.transform","title":"transform(self, blob)","text":"

                                    Transform the blob into a Results.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\"\"\"\n    ts0 = datetime.datetime.now()\n    results = Results()\n    ru_factory = RuleUseFactory(self.get_timestamp())\n    ru_list = ru_factory.make_list(blob)\n    tanium_oscal_factory = TaniumOscalFactory(\n        self.get_timestamp(),\n        ru_list,\n        self.blocksize,\n        self.cpus_max,\n        self.cpus_min,\n        self.checking,\n        self.caching,\n        self.aggregate\n    )\n    results.__root__ = tanium_oscal_factory.results\n    ts1 = datetime.datetime.now()\n    self._analysis = tanium_oscal_factory.analysis\n    self._analysis.append(f'transform time: {ts1-ts0}')\n    return results\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumTransformer","title":" TaniumTransformer (TaniumResultToOscalARTransformer) ","text":"

                                    Legacy class name.

                                    Source code in trestle/transforms/implementations/tanium.py
                                    class TaniumTransformer(TaniumResultToOscalARTransformer):\n\"\"\"Legacy class name.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/","title":"xccdf","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf","title":"trestle.transforms.implementations.xccdf","text":"

                                    Facilitate OSCAL-XCCDF transformation.

                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse","title":" RuleUse ","text":"

                                    Represents one rule of XCCDF data.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    class RuleUse():\n\"\"\"Represents one rule of XCCDF data.\"\"\"\n\n    def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self.id_ = args['id_']\n        self.target = args['target']\n        self.target_type = args['target_type']\n        self.host_name = args['host_name']\n        self.benchmark_href = args['benchmark_href']\n        self.benchmark_id = args['benchmark_id']\n        self.scanner_name = args['scanner_name']\n        self.scanner_version = args['scanner_version']\n        self.idref = args['idref']\n        self.version = args['version']\n        self.time = args['time']\n        self.result = args['result']\n        self.severity = args['severity']\n        self.weight = args['weight']\n\n    @property\n    def inventory_key(self):\n\"\"\"Derive inventory key.\"\"\"\n        if self.host_name is None:\n            # OpenScap 1.3.3\n            rval = self.target + ':' + self.target_type\n        else:\n            # OpenScap 1.3.5\n            rval = self.host_name + ':' + self.target_type\n        return rval\n\n    @property\n    def ns(self):\n\"\"\"Derive namespace.\"\"\"\n        return f'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/{self.scanner_name}'  # noqa: E231\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse.inventory_key","title":"inventory_key property readonly","text":"

                                    Derive inventory key.

                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse.ns","title":"ns property readonly","text":"

                                    Derive namespace.

                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse.__init__","title":"__init__(self, args) special","text":"

                                    Initialize given specified args.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self.id_ = args['id_']\n    self.target = args['target']\n    self.target_type = args['target_type']\n    self.host_name = args['host_name']\n    self.benchmark_href = args['benchmark_href']\n    self.benchmark_id = args['benchmark_id']\n    self.scanner_name = args['scanner_name']\n    self.scanner_version = args['scanner_version']\n    self.idref = args['idref']\n    self.version = args['version']\n    self.time = args['time']\n    self.result = args['result']\n    self.severity = args['severity']\n    self.weight = args['weight']\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer","title":" XccdfResultToOscalARTransformer (ResultsTransformer) ","text":"

                                    Interface for Xccdf transformer.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    class XccdfResultToOscalARTransformer(ResultsTransformer):\n\"\"\"Interface for Xccdf transformer.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._modes = {}\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"Analysis.\"\"\"\n        return self._results_factory.analysis\n\n    @property\n    def checking(self):\n\"\"\"Return checking.\"\"\"\n        return self._modes.get('checking', False)\n\n    @property\n    def tags(self):\n\"\"\"Return tags.\"\"\"\n        return self._tags\n\n    def set_tags(self, tags: Dict[str, str]) -> None:\n\"\"\"Keep tags info (property name to property class).\"\"\"\n        self._tags = tags\n\n    def set_title(self, title: str) -> None:\n\"\"\"Keep title info.\"\"\"\n        self._title = title\n\n    def set_description(self, description: str) -> None:\n\"\"\"Keep description info.\"\"\"\n        self._description = description\n\n    def set_type(self, type_: str) -> None:\n\"\"\"Keep type info.\"\"\"\n        self._type = type_\n\n    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n        if modes is not None:\n            self._modes = modes\n\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n        The expected blob is a string that is one of:\n            - data from OpenShift Compliance Operator (json, yaml, xml)\n            - data from Auditree XCCDF fetcher/check (json)\n        \"\"\"\n        self._results_factory = _OscalResultsFactory(\n            self._title, self._description, self._type, self.get_timestamp(), self.checking, self.tags\n        )\n        results = self._ingest_xml(blob)\n        if results is None:\n            results = self._ingest_json(blob)\n        if results is None:\n            results = self._ingest_yaml(blob)\n        return results\n\n    def _ingest_xml(self, blob: str) -> Optional[Results]:\n\"\"\"Ingest xml data.\"\"\"\n        # ?xml data\n        if blob.startswith('<?xml'):\n            resource = blob\n            self._results_factory.ingest_xml(resource)\n        else:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_configmaps(self, jdata: dict) -> None:\n\"\"\"Ingest configmaps.\"\"\"\n        items = jdata['items']\n        for item in items:\n            if 'data' in item.keys():\n                data = item['data']\n                if 'results' in data:\n                    resource = item\n                    self._results_factory.ingest(resource)\n\n    def _ingest_auditree(self, jdata: dict) -> None:\n\"\"\"Ingest auditree.\"\"\"\n        for key in jdata.keys():\n            for group in jdata[key]:\n                for cluster in jdata[key][group]:\n                    if 'resources' in cluster:\n                        for resource in cluster['resources']:\n                            self._results_factory.ingest(resource)\n\n    def _ingest_json(self, blob: str) -> Optional[Results]:\n\"\"\"Ingest json data.\"\"\"\n        try:\n            # ? configmaps or auditree data\n            jdata = json.loads(blob)\n            # https://docs.openshift.com/container-platform/3.7/rest_api/api/v1.ConfigMap.html#Get-api-v1-namespaces-namespace-configmaps-name\n            if 'kind' in jdata.keys() and jdata['kind'] == 'ConfigMapList' and 'items' in jdata.keys():\n                self._ingest_configmaps(jdata)\n            # https://github.com/ComplianceAsCode/auditree-arboretum/blob/main/arboretum/kubernetes/fetchers/fetch_cluster_resource.py\n            else:\n                self._ingest_auditree(jdata)\n        except json.decoder.JSONDecodeError:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_yaml(self, blob: str) -> Results:\n\"\"\"Ingest yaml data.\"\"\"\n        try:\n            # ? yaml data\n            yaml = YAML(typ='safe')\n            resource = yaml.load(blob)\n            self._results_factory.ingest(resource)\n        except Exception as e:\n            raise RuntimeError(e)\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.analysis","title":"analysis: List[str] property readonly","text":"

                                    Analysis.

                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.checking","title":"checking property readonly","text":"

                                    Return checking.

                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.tags","title":"tags property readonly","text":"

                                    Return tags.

                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.__init__","title":"__init__(self) special","text":"

                                    Initialize.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._modes = {}\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_description","title":"set_description(self, description)","text":"

                                    Keep description info.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def set_description(self, description: str) -> None:\n\"\"\"Keep description info.\"\"\"\n    self._description = description\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_modes","title":"set_modes(self, modes)","text":"

                                    Keep modes info.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n    if modes is not None:\n        self._modes = modes\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_tags","title":"set_tags(self, tags)","text":"

                                    Keep tags info (property name to property class).

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def set_tags(self, tags: Dict[str, str]) -> None:\n\"\"\"Keep tags info (property name to property class).\"\"\"\n    self._tags = tags\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_title","title":"set_title(self, title)","text":"

                                    Keep title info.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def set_title(self, title: str) -> None:\n\"\"\"Keep title info.\"\"\"\n    self._title = title\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_type","title":"set_type(self, type_)","text":"

                                    Keep type info.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def set_type(self, type_: str) -> None:\n\"\"\"Keep type info.\"\"\"\n    self._type = type_\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.transform","title":"transform(self, blob)","text":"

                                    Transform the blob into a Results.

                                    The expected blob is a string that is one of: - data from OpenShift Compliance Operator (json, yaml, xml) - data from Auditree XCCDF fetcher/check (json)

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n    The expected blob is a string that is one of:\n        - data from OpenShift Compliance Operator (json, yaml, xml)\n        - data from Auditree XCCDF fetcher/check (json)\n    \"\"\"\n    self._results_factory = _OscalResultsFactory(\n        self._title, self._description, self._type, self.get_timestamp(), self.checking, self.tags\n    )\n    results = self._ingest_xml(blob)\n    if results is None:\n        results = self._ingest_json(blob)\n    if results is None:\n        results = self._ingest_yaml(blob)\n    return results\n
                                    "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfTransformer","title":" XccdfTransformer (XccdfResultToOscalARTransformer) ","text":"

                                    Legacy class name.

                                    Source code in trestle/transforms/implementations/xccdf.py
                                    class XccdfTransformer(XccdfResultToOscalARTransformer):\n\"\"\"Legacy class name.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.results/","title":"results","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results","title":"trestle.transforms.results","text":"

                                    Define Results class returned by transformers.

                                    "},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results","title":" Results (OscalBaseModel) pydantic-model","text":"

                                    Transformer results as a list.

                                    Source code in trestle/transforms/results.py
                                    class Results(OscalBaseModel):\n\"\"\"Transformer results as a list.\"\"\"\n\n    __root__: List[Result] = []\n
                                    "},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__root__","title":"__root__: List[trestle.oscal.assessment_results.Result] pydantic-field special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/","title":"transformer_factory","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory","title":"trestle.transforms.transformer_factory","text":"

                                    Define the TransformerFactory and corresponding transformer classes it creates.

                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.FromOscalTransformer","title":" FromOscalTransformer (TransformerBase) ","text":"

                                    Abstract interface for transformers from OSCAL.

                                    Source code in trestle/transforms/transformer_factory.py
                                    class FromOscalTransformer(TransformerBase):\n\"\"\"Abstract interface for transformers from OSCAL.\"\"\"\n\n    @abstractmethod\n    def transform(self, obj: OscalBaseModel) -> str:\n\"\"\"Transform the from OSCAL.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.FromOscalTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.FromOscalTransformer.transform","title":"transform(self, obj)","text":"

                                    Transform the from OSCAL.

                                    Source code in trestle/transforms/transformer_factory.py
                                    @abstractmethod\ndef transform(self, obj: OscalBaseModel) -> str:\n\"\"\"Transform the from OSCAL.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ResultsTransformer","title":" ResultsTransformer (TransformerBase) ","text":"

                                    Abstract interface for transformers that specifically return Results.

                                    Source code in trestle/transforms/transformer_factory.py
                                    class ResultsTransformer(TransformerBase):\n\"\"\"Abstract interface for transformers that specifically return Results.\"\"\"\n\n    @abstractmethod\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into Results.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ResultsTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ResultsTransformer.transform","title":"transform(self, blob)","text":"

                                    Transform the blob into Results.

                                    Source code in trestle/transforms/transformer_factory.py
                                    @abstractmethod\ndef transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into Results.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ToOscalTransformer","title":" ToOscalTransformer (TransformerBase) ","text":"

                                    Abstract interface for transformers to OSCAL.

                                    Source code in trestle/transforms/transformer_factory.py
                                    class ToOscalTransformer(TransformerBase):\n\"\"\"Abstract interface for transformers to OSCAL.\"\"\"\n\n    @abstractmethod\n    def transform(self, obj: str) -> OscalBaseModel:\n\"\"\"Transform the to OSCAL.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ToOscalTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ToOscalTransformer.transform","title":"transform(self, obj)","text":"

                                    Transform the to OSCAL.

                                    Source code in trestle/transforms/transformer_factory.py
                                    @abstractmethod\ndef transform(self, obj: str) -> OscalBaseModel:\n\"\"\"Transform the to OSCAL.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase","title":" TransformerBase (ABC) ","text":"

                                    Abstract base interface for all transformers.

                                    Source code in trestle/transforms/transformer_factory.py
                                    class TransformerBase(ABC):\n\"\"\"Abstract base interface for all transformers.\"\"\"\n\n    # the current time for consistent timestamping\n    _timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc).isoformat()\n\n    @staticmethod\n    def set_timestamp(value: str) -> None:\n\"\"\"Set the default timestamp value.\"\"\"\n        datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')\n        TransformerBase._timestamp = value\n\n    @staticmethod\n    def get_timestamp() -> str:\n\"\"\"Get the default timestamp value.\"\"\"\n        return TransformerBase._timestamp\n\n    @abstractmethod\n    def transform(self, blob: Any) -> Any:\n\"\"\"Transform the blob into a general OscalBaseModel.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase.get_timestamp","title":"get_timestamp() staticmethod","text":"

                                    Get the default timestamp value.

                                    Source code in trestle/transforms/transformer_factory.py
                                    @staticmethod\ndef get_timestamp() -> str:\n\"\"\"Get the default timestamp value.\"\"\"\n    return TransformerBase._timestamp\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase.set_timestamp","title":"set_timestamp(value) staticmethod","text":"

                                    Set the default timestamp value.

                                    Source code in trestle/transforms/transformer_factory.py
                                    @staticmethod\ndef set_timestamp(value: str) -> None:\n\"\"\"Set the default timestamp value.\"\"\"\n    datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')\n    TransformerBase._timestamp = value\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase.transform","title":"transform(self, blob)","text":"

                                    Transform the blob into a general OscalBaseModel.

                                    Source code in trestle/transforms/transformer_factory.py
                                    @abstractmethod\ndef transform(self, blob: Any) -> Any:\n\"\"\"Transform the blob into a general OscalBaseModel.\"\"\"\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory","title":" TransformerFactory ","text":"

                                    Perform registration and creation of transformers.

                                    Source code in trestle/transforms/transformer_factory.py
                                    class TransformerFactory:\n\"\"\"Perform registration and creation of transformers.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize the transformers dictionary as empty.\"\"\"\n        self._transformers: Dict[str, Type[TransformerBase]] = {}\n\n    def register_transformer(self, name: str, transformer: Type[TransformerBase]) -> None:\n\"\"\"\n        Register the transformer.\n\n        This registers transformers in the factory so they may be created by name.\n\n        Args:\n            name (str): The name of the transformer.\n            transformer (TransformerBase): The transformer class to be registered.\n\n        Returns:\n            None\n        \"\"\"\n        self._transformers[name] = transformer\n\n    def get(self, name: str) -> TransformerBase:\n\"\"\"\n        Create an instance of the desired transformer based its name.\n\n        Args:\n            name (str): The name of the transformer.\n\n        Returns:\n            An instance of the desired transformer.\n\n        Raises:\n            TrestleError: if the name does not exist in the registry.\n        \"\"\"\n        t = self._transformers.get(name)\n        if t is not None:\n            return t()\n        raise TrestleError(f'Error getting non-registered transform {name}')\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory.__init__","title":"__init__(self) special","text":"

                                    Initialize the transformers dictionary as empty.

                                    Source code in trestle/transforms/transformer_factory.py
                                    def __init__(self) -> None:\n\"\"\"Initialize the transformers dictionary as empty.\"\"\"\n    self._transformers: Dict[str, Type[TransformerBase]] = {}\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory.get","title":"get(self, name)","text":"

                                    Create an instance of the desired transformer based its name.

                                    Parameters:

                                    Name Type Description Default name str

                                    The name of the transformer.

                                    required

                                    Returns:

                                    Type Description TransformerBase

                                    An instance of the desired transformer.

                                    Exceptions:

                                    Type Description TrestleError

                                    if the name does not exist in the registry.

                                    Source code in trestle/transforms/transformer_factory.py
                                    def get(self, name: str) -> TransformerBase:\n\"\"\"\n    Create an instance of the desired transformer based its name.\n\n    Args:\n        name (str): The name of the transformer.\n\n    Returns:\n        An instance of the desired transformer.\n\n    Raises:\n        TrestleError: if the name does not exist in the registry.\n    \"\"\"\n    t = self._transformers.get(name)\n    if t is not None:\n        return t()\n    raise TrestleError(f'Error getting non-registered transform {name}')\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory.register_transformer","title":"register_transformer(self, name, transformer)","text":"

                                    Register the transformer.

                                    This registers transformers in the factory so they may be created by name.

                                    Parameters:

                                    Name Type Description Default name str

                                    The name of the transformer.

                                    required transformer TransformerBase

                                    The transformer class to be registered.

                                    required

                                    Returns:

                                    Type Description None

                                    None

                                    Source code in trestle/transforms/transformer_factory.py
                                    def register_transformer(self, name: str, transformer: Type[TransformerBase]) -> None:\n\"\"\"\n    Register the transformer.\n\n    This registers transformers in the factory so they may be created by name.\n\n    Args:\n        name (str): The name of the transformer.\n        transformer (TransformerBase): The transformer class to be registered.\n\n    Returns:\n        None\n    \"\"\"\n    self._transformers[name] = transformer\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/","title":"transformer_helper","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper","title":"trestle.transforms.transformer_helper","text":"

                                    Transformer helper functions.

                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting","title":" PropertyAccounting ","text":"

                                    Property accounting class.

                                    Help transformers do accounting.

                                    Each time a new record is processed the transformer calls count_group. For each attribute on that record, the transformer calls count_property. - If the property already exactly exists, then its count is incremented. - Otherwise, a new entry is made and the count for that property is set to 1. When the transformer wants to know if a property (name, value, ns, and class) is common to all records for the group, is_common_property is employed to check that the number of records in the group is equal to the number of duplicates there are for the property. If equal, then the property is common.

                                    Source code in trestle/transforms/transformer_helper.py
                                    class PropertyAccounting():\n\"\"\"Property accounting class.\n\n    Help transformers do accounting.\n\n    > Each time a new record is processed the transformer calls count_group.\n    > For each attribute on that record, the transformer calls count_property.\n      - If the property already exactly exists, then its count is incremented.\n      - Otherwise, a new entry is made and the count for that property is set to 1.\n    > When the transformer wants to know if a property (name, value, ns, and class)\n      is common to all records for the group, is_common_property is employed to check\n      that the number of records in the group is equal to the number of duplicates\n      there are for the property. If equal, then the property is common.\n    \"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._group_map: Dict[str, int] = {}\n        self._property_map: Dict[str, Dict[str, int]] = {}\n\n    def count_group(self, group: Optional[str] = None) -> None:\n\"\"\"Group accounting.\"\"\"\n        if not group:\n            raise TrestleError('count_group created with group=None')\n        if group not in self._group_map:\n            self._group_map[group] = 0\n        self._group_map[group] += 1\n\n    def count_property(\n        self,\n        group: str,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> None:\n\"\"\"Property accounting.\"\"\"\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if group not in self._property_map:\n            self._property_map[group] = {}\n        if key not in self._property_map[group]:\n            self._property_map[group][key] = 0\n        self._property_map[group][key] += 1\n\n    def is_common_property(\n        self,\n        group: str,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> bool:\n\"\"\"Check for common property.\"\"\"\n        rval = False\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if group in self._group_map and key in self._property_map[group]:\n            rval = self._group_map[group] == self._property_map[group][key]\n        return rval\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.__init__","title":"__init__(self) special","text":"

                                    Initialize.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._group_map: Dict[str, int] = {}\n    self._property_map: Dict[str, Dict[str, int]] = {}\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.count_group","title":"count_group(self, group=None)","text":"

                                    Group accounting.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def count_group(self, group: Optional[str] = None) -> None:\n\"\"\"Group accounting.\"\"\"\n    if not group:\n        raise TrestleError('count_group created with group=None')\n    if group not in self._group_map:\n        self._group_map[group] = 0\n    self._group_map[group] += 1\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.count_property","title":"count_property(self, group, name=None, value=None, class_=None, ns=None)","text":"

                                    Property accounting.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def count_property(\n    self,\n    group: str,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> None:\n\"\"\"Property accounting.\"\"\"\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if group not in self._property_map:\n        self._property_map[group] = {}\n    if key not in self._property_map[group]:\n        self._property_map[group][key] = 0\n    self._property_map[group][key] += 1\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.is_common_property","title":"is_common_property(self, group, name=None, value=None, class_=None, ns=None)","text":"

                                    Check for common property.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def is_common_property(\n    self,\n    group: str,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> bool:\n\"\"\"Check for common property.\"\"\"\n    rval = False\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if group in self._group_map and key in self._property_map[group]:\n        rval = self._group_map[group] == self._property_map[group][key]\n    return rval\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager","title":" PropertyManager ","text":"

                                    Property manager class.

                                    Help transformer manage properties.

                                    Use materialize to: fetch a property from cache (if caching), else create a new property instance and keep in cache (if caching). Use put_common_property to: keep common properties for each group. Use get_common_properties to: recall the list of common properties for the group.

                                    Source code in trestle/transforms/transformer_helper.py
                                    class PropertyManager():\n\"\"\"Property manager class.\n\n    Help transformer manage properties.\n\n    > Use materialize to: fetch a property from cache (if caching), else create a new\n      property instance and keep in cache (if caching).\n    > Use put_common_property to: keep common properties for each group.\n    > Use get_common_properties to: recall the list of common properties for the group.\n    \"\"\"\n\n    def __init__(self, caching: bool = True, checking: bool = False) -> None:\n\"\"\"Initialize.\"\"\"\n        self._caching = caching\n        self._checking = checking\n        self._requests = 0\n        self._hits = 0\n        self._map_unique: Dict[str, Any] = {}\n        self._map_common: Dict[str, Dict[str, Property]] = {}\n\n    @property\n    def requests(self) -> int:\n\"\"\"Cache requests.\"\"\"\n        return self._requests\n\n    @property\n    def hits(self) -> int:\n\"\"\"Cache hits.\"\"\"\n        return self._hits\n\n    def materialize(\n        self,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> Property:\n\"\"\"Get property from cache or create new property.\"\"\"\n        self._requests += 1\n        # try fetch from cache\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if key in self._map_unique:\n            self._hits += 1\n            return self._map_unique[key]\n        # create new property and put into cache if caching\n        prop = self._create(name=name, value=value, class_=class_, ns=ns)\n        if self._caching:\n            self._map_unique[key] = prop\n        return prop\n\n    def put_common_property(\n        self,\n        group: Optional[str] = None,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> None:\n\"\"\"Remember common property.\"\"\"\n        if not group:\n            raise TrestleError('put_common_property created with group=None')\n        if group not in self._map_common:\n            self._map_common[group] = {}\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if key not in self._map_common[group]:\n            prop = self.materialize(name, value, class_, ns)\n            self._map_common[group][key] = prop\n\n    def get_common_properties(self, group: Optional[str] = None) -> Optional[List[Property]]:\n\"\"\"Recall common properties for the group.\"\"\"\n        rval = None\n        if not group:\n            raise TrestleError('get_common_properties created with group=None')\n        if group in self._map_common:\n            rval = list(self._map_common[group].values())\n        return rval\n\n    def _create(\n        self,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> Property:\n\"\"\"Create new property.\"\"\"\n        if self._checking:\n            return Property(name=name, value=value, class_=class_, ns=ns)  # type: ignore\n        return Property.construct(name=name, value=value, class_=class_, ns=ns)  # type: ignore\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.hits","title":"hits: int property readonly","text":"

                                    Cache hits.

                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.requests","title":"requests: int property readonly","text":"

                                    Cache requests.

                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.__init__","title":"__init__(self, caching=True, checking=False) special","text":"

                                    Initialize.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def __init__(self, caching: bool = True, checking: bool = False) -> None:\n\"\"\"Initialize.\"\"\"\n    self._caching = caching\n    self._checking = checking\n    self._requests = 0\n    self._hits = 0\n    self._map_unique: Dict[str, Any] = {}\n    self._map_common: Dict[str, Dict[str, Property]] = {}\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.get_common_properties","title":"get_common_properties(self, group=None)","text":"

                                    Recall common properties for the group.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def get_common_properties(self, group: Optional[str] = None) -> Optional[List[Property]]:\n\"\"\"Recall common properties for the group.\"\"\"\n    rval = None\n    if not group:\n        raise TrestleError('get_common_properties created with group=None')\n    if group in self._map_common:\n        rval = list(self._map_common[group].values())\n    return rval\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.materialize","title":"materialize(self, name=None, value=None, class_=None, ns=None)","text":"

                                    Get property from cache or create new property.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def materialize(\n    self,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> Property:\n\"\"\"Get property from cache or create new property.\"\"\"\n    self._requests += 1\n    # try fetch from cache\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if key in self._map_unique:\n        self._hits += 1\n        return self._map_unique[key]\n    # create new property and put into cache if caching\n    prop = self._create(name=name, value=value, class_=class_, ns=ns)\n    if self._caching:\n        self._map_unique[key] = prop\n    return prop\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.put_common_property","title":"put_common_property(self, group=None, name=None, value=None, class_=None, ns=None)","text":"

                                    Remember common property.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def put_common_property(\n    self,\n    group: Optional[str] = None,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> None:\n\"\"\"Remember common property.\"\"\"\n    if not group:\n        raise TrestleError('put_common_property created with group=None')\n    if group not in self._map_common:\n        self._map_common[group] = {}\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if key not in self._map_common[group]:\n        prop = self.materialize(name, value, class_, ns)\n        self._map_common[group][key] = prop\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.TransformerHelper","title":" TransformerHelper ","text":"

                                    OSCAL transformer helper.

                                    Source code in trestle/transforms/transformer_helper.py
                                    class TransformerHelper():\n\"\"\"OSCAL transformer helper.\"\"\"\n\n    def remove_common_observation_properties(self, observations: List[Observation]) -> List[Property]:\n\"\"\"Remove common observation properties.\"\"\"\n        common_props = []\n        props = {}\n        # count each property occurrence in each observation\n        props_occurrence_counts = self._get_property_occurrence_counts(observations)\n        # remove common properties from observation\n        for key in props_occurrence_counts.keys():\n            # skip property if not identical for each and every observation\n            if props_occurrence_counts[key] != len(observations):\n                continue\n            # remove property from each observation and keep one instance\n            for observation in observations:\n                for prop in as_list(observation.props):\n                    if key == f'{prop.name}:{prop.value}:{prop.class_}':\n                        props[key] = prop\n                        observation.props.remove(prop)\n                        break\n        # formulate list of removed properties\n        for key in props.keys():\n            common_props.append(props[key])\n        # return list of removed properties\n        return common_props\n\n    def _get_property_occurrence_counts(self, observations: List[Observation]) -> Dict[str, Property]:\n\"\"\"Count each property occurrence in each observation.\"\"\"\n        property_occurences = {}\n        for observation in observations:\n            for prop in observation.props:\n                key = f'{prop.name}:{prop.value}:{prop.class_}'\n                if key not in property_occurences.keys():\n                    property_occurences[key] = 0\n                property_occurences[key] += 1\n        return property_occurences\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.TransformerHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.TransformerHelper.remove_common_observation_properties","title":"remove_common_observation_properties(self, observations)","text":"

                                    Remove common observation properties.

                                    Source code in trestle/transforms/transformer_helper.py
                                    def remove_common_observation_properties(self, observations: List[Observation]) -> List[Property]:\n\"\"\"Remove common observation properties.\"\"\"\n    common_props = []\n    props = {}\n    # count each property occurrence in each observation\n    props_occurrence_counts = self._get_property_occurrence_counts(observations)\n    # remove common properties from observation\n    for key in props_occurrence_counts.keys():\n        # skip property if not identical for each and every observation\n        if props_occurrence_counts[key] != len(observations):\n            continue\n        # remove property from each observation and keep one instance\n        for observation in observations:\n            for prop in as_list(observation.props):\n                if key == f'{prop.name}:{prop.value}:{prop.class_}':\n                    props[key] = prop\n                    observation.props.remove(prop)\n                    break\n    # formulate list of removed properties\n    for key in props.keys():\n        common_props.append(props[key])\n    # return list of removed properties\n    return common_props\n
                                    "},{"location":"api_reference/trestle.transforms.transformer_singleton/","title":"transformer_singleton","text":"

                                    handler: python

                                    "},{"location":"api_reference/trestle.transforms.transformer_singleton/#trestle.transforms.transformer_singleton","title":"trestle.transforms.transformer_singleton","text":"

                                    Create the singleton transformer factory here.

                                    "},{"location":"api_reference/trestle.transforms.transformer_singleton/#trestle.transforms.transformer_singleton.transformer_factory","title":"transformer_factory","text":""},{"location":"contributing/DCO/","title":"Developer Certificate of Originality","text":"
                                    Developer Certificate of Origin\nVersion 1.1\n\nCopyright (C) 2004, 2006 The Linux Foundation and its contributors.\n660 York Street, Suite 102,\nSan Francisco, CA 94110 USA\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\n\nDeveloper's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n(a) The contribution was created in whole or in part by me and I\nhave the right to submit it under the open source license\nindicated in the file; or\n\n(b) The contribution is based upon previous work that, to the best\nof my knowledge, is covered under an appropriate open source\nlicense and I have the right under that license to submit that\nwork with modifications, whether created in whole or in part\nby me, under the same open source license (unless I am\npermitted to submit under a different license), as indicated\nin the file; or\n\n(c) The contribution was provided directly to me by some other\nperson who certified (a), (b) or (c) and I have not modified\nit.\n\n(d) I understand and agree that this project and the contribution\nare public and that a record of the contribution (including all\npersonal information I submit with it, including my sign-off) is\nmaintained indefinitely and may be redistributed consistent with\nthis project or the open source license(s) involved.\n
                                    "},{"location":"contributing/github_actions_setup/","title":"Github actions setup","text":"

                                    Github actions contains variables which have opaque values to a user. The variables are documented here such that trestle can be setup on a fork etc.

                                    "},{"location":"contributing/github_actions_setup/#secrets","title":"Secrets","text":"
                                    • ADMIN_PAT: Github PAT with sufficient write access to merge content into develop and commit to gh-pages and main

                                    • SONAR_TOKEN: Token to sonarcloud with rights to the appropriate project.

                                    "},{"location":"contributing/github_actions_setup/#repository-level-variables","title":"Repository level variables","text":"
                                    • PYTHON_MIN: Minimum test version of python e.g. 3.9
                                    • PYTHON_MAX: Maxmimum test version of python e.g. 3.11
                                    "},{"location":"contributing/github_actions_setup/#authorization-with-pypi","title":"Authorization with pypi","text":"

                                    Pypi authorization must be setup following the procedure in the following documents

                                    • https://docs.pypi.org/trusted-publishers/adding-a-publisher/
                                    "},{"location":"contributing/mkdocs_contributing/","title":"Contributing overview","text":""},{"location":"contributing/mkdocs_contributing/#contributing-in-general","title":"Contributing In General","text":"

                                    Our project welcomes external contributions. If you have an itch, please feel free to scratch it.

                                    To contribute code or documentation, please submit a pull request.

                                    A good way to familiarize yourself with the codebase and contribution process is to look for and tackle low-hanging fruit in the issue tracker. Before embarking on a more ambitious contribution, please quickly get in touch with us.

                                    Note: We appreciate your effort, and want to avoid a situation where a contribution requires extensive rework (by you or by us), sits in backlog for a long time, or cannot be accepted at all!

                                    We have also adopted Contributor Covenant Code of Conduct.

                                    "},{"location":"contributing/mkdocs_contributing/#proposing-new-features","title":"Proposing new features","text":"

                                    If you would like to implement a new feature, please raise an issue labelled enhancement before sending a pull request so the feature can be discussed. This is to avoid you wasting your valuable time working on a feature that the project developers are not interested in accepting into the code base.

                                    "},{"location":"contributing/mkdocs_contributing/#fixing-bugs","title":"Fixing bugs","text":"

                                    If you would like to fix a bug, please raise an issue labelled bug before sending a pull request so it can be tracked.

                                    "},{"location":"contributing/mkdocs_contributing/#merge-approval","title":"Merge approval","text":"

                                    The project maintainers use LGTM (Looks Good To Me) in comments on the code review to indicate acceptance. A change requires LGTMs from one of the maintainers.

                                    For a list of the maintainers, see the maintainers page.

                                    "},{"location":"contributing/mkdocs_contributing/#trestle-merging-and-release-workflow","title":"Trestle merging and release workflow","text":"

                                    trestle is operating on a simple, yet opinionated, method for continuous integration. It's designed to give developers a coherent understanding of the objectives of other past developers. The criteria for this are below. Trestle effectively uses a gitflow workflow with one modification: PR's merge into develop are squash merged as one commit.

                                    In trestle's CI environment this results in the following rules:

                                    1. All Commit's MUST be signed off with git commit --signoff irrespective of the author's affiliation. This ensures all code can be attributed.
                                    2. This is enforced by DCO bot and can be overrided by maintainers presuming at least one commit is signed-off.
                                    3. All commits SHOULD use conventional commits
                                    4. This is as github, when only one commit is in a PR, will use the native git commit message as the merge commit title.
                                      1. When only a single commit is provided the commit MUST be an conventional commit and will be checked the Lint PR aciton.
                                    5. All PR's title's MUST be formed as an convention commit
                                    6. This is checked by the Lint PR action
                                    7. All PR's to develop and hotfix PR's to main must close at least one issue by linking the PR to an issue.
                                    8. Trestle will release on demand the default approach for a hot fix should be to merge into develop, followed by releasing to main, unless this will release functionality that is not ready.
                                    9. Each feature/fix/chore (PR into develop) be represented by a single commit into develop / main with a coherent title (in the PR).
                                    10. The trestle preference for doing this is to use squash merge functionality when merging a PR into develop.
                                    11. Developers MUST pass the required CI checks for each PR.
                                    12. Developers are encouraged to use GitHub's automated merge process where possible to keep the number of active PR's low.
                                    "},{"location":"contributing/mkdocs_contributing/#merge-details-for-committers","title":"Merge details for committers:","text":"
                                    1. All merges into develop MUST be conducted by a squash-merge
                                    2. All merges from develop into main MUST be done by a merge commit (e.g. preserving the history of commits into the develop branch).
                                    3. Hotfixes into main, not via develop, MUST be done via a squash merge.
                                    4. Merge's into any branch excluding main and develop are at the developers choice.
                                    5. Use of autocommit is encouraged to ensure commit messages and squash vs merge commit are completed properly.
                                    "},{"location":"contributing/mkdocs_contributing/#working-from-a-fork","title":"Working from a fork","text":"
                                    1. In order not to break Github Actions security model SonarCloud will not run on a fork.
                                    2. Given this a maintainer MAY determine that sonar needs to be run and ask you to first merge your branch to a staging branch, after reviewing for security risks in the CI pipeline.
                                    3. From this staging branch sonar would be run and then the code merged.
                                    "},{"location":"contributing/mkdocs_contributing/#typing-docstrings-and-documentation","title":"Typing, docstrings and documentation","text":"

                                    trestle has a goal of using PEP 484 type annotations where possible / practical. The devops process does not strictly enforce typing, however, the expectation is that type coverage is added for new commits with a focus on quality over quantity (e.g. don't add Any everywhere just to meet coverage requirements). Python typing of functions is an active work in progress.

                                    mkbuild is used to generate the trestle documenation site. The mkbuild website includes an API reference section generated from the code. Docstrings within the code are expected to follow google style docstrings.

                                    "},{"location":"contributing/mkdocs_contributing/#legal","title":"Legal","text":"

                                    Each source file must include a license header for the Apache Software License 2.0. Using the SPDX format is the simplest approach. e.g.

                                    # Copyright (c) 2020 IBM Corp. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n

                                    We have tried to make it as easy as possible to make contributions. This applies to how we handle the legal aspects of contribution. We use the same approach - the Developer's Certificate of Origin 1.1 (DCO) - that the Linux\u00ae Kernel community uses to manage code contributions.

                                    We simply ask that when submitting a patch for review, the developer must include a sign-off statement in the commit message.

                                    Here is an example Signed-off-by line, which indicates that the submitter accepts the DCO:

                                    Signed-off-by: John Doe <john.doe@example.com>\n

                                    You can include this automatically when you commit a change to your local git repository using the following command:

                                    git commit --signoff\n

                                    Note that DCO signoff is enforced by DCO bot. Missing DCO's will be required to be rebased with a signed off commit before being accepted.

                                    "},{"location":"contributing/mkdocs_contributing/#setup-developing-trestle","title":"Setup - Developing trestle","text":""},{"location":"contributing/mkdocs_contributing/#does-trestle-run-correctly-on-my-platform","title":"Does trestle run correctly on my platform","text":"
                                    • (Optional) setup a venv for python
                                    • Run make develop
                                    • This will install all python dependencies
                                    • It will also checkout the submodules required for testing.
                                    • Run make test
                                    • This should run on all platforms
                                    "},{"location":"contributing/mkdocs_contributing/#setting-up-vscode-for-python","title":"Setting up vscode for python.","text":"
                                    • Use the following commands to setup python:
                                    python3 -m venv venv\n. ./venv/bin/activate\n# for zsh put .[dev] in quotes as below\npip install -q -e \".[dev]\" --upgrade --upgrade-strategy eager\n
                                    • Install vscode plugin Python extension for Visual Studio Code

                                    • Enable yapf for code formatting

                                    • Enable flake8 for code linting

                                    "},{"location":"contributing/mkdocs_contributing/#testing-python-in-vscode","title":"Testing python in vscode","text":"

                                    Tests should be in the test subdirectory. Each file should be named test_*.py and each test function should be named *_test().

                                    Note that with Python3 there should be no need for init.py in directories.

                                    Test discovery should be automatic when you select a .py file for editing. After tests are discovered a flask icon will appear on the left and you can select it to see a panel listing of your tests. In addition your test functions will be annotated with Run/Debug so they can be launched directly from the editor. When everything is set up properly you should be able to step through your test code - which is important.

                                    Sometimes the discovery fails - and you may need to resort to uninstalling the python extension and reinstalling it - perhaps also shutting down code and restarting. This is a lightweight operation and seems to be safe and usually fixes any problems.

                                    Test disovery will fail or stop if any of the tests have errors in them - so be sure to monitor the Problems panel at the bottom for problems in the code.

                                    Note that there are many panels available in Output - so be sure to check Python Test Log for errors and output from the tests.

                                    pytest fixtures are available to allow provision of common functionality. See conftest.py and tmp_dir for an example.

                                    "},{"location":"contributing/mkdocs_contributing/#nist-reference-data-for-testing","title":"NIST reference data for testing.","text":"

                                    Trestle relies on reference data from two NIST repositories for testing:

                                    • https://github.com/usnistgov/OSCAL
                                    • https://github.com/usnistgov/oscal-content

                                    Both of these repositories are submodules in the trestle project. In order to develop / test trestle the submodules must be checked out with git submodule update --init or make submodules.

                                    "},{"location":"contributing/mkdocs_contributing/#code-style-and-formating","title":"Code style and formating","text":"

                                    trestle uses yapf for code formatting and flake8 for code styling. It also uses pre-commit hooks that are integrated into the development process and the CI. When you run make develop you are ensuring that the pre-commit hooks are installed and updated to their latest versions for this repository. This ensures that all delivered code has been properly formatted and passes the linter rules. See the pre-commit configuration file for details on yapf and flake8 configurations.

                                    Since yapf and flake8 are installed as part of the pre-commit hooks, running yapf and flake8 manually must be done through pre-commit. See examples below:

                                    make code-format\nmake code-lint\n

                                    ...will run yapf and flake8 on the entire repo and is equivalent to:

                                    pre-commit run yapf --all-files\npre-commit run flake8 --all-files\n

                                    ...and when looking to limit execution to a subset of files do similar to:

                                    pre-commit run yapf --files trestle/*\npre-commit run flake8 --files trestle/*\n

                                    Note that in both of these cases autogenerated files under trestle/oscal are excluded. Note that for IDE support setup.cfg maintains a cache of flake8 configuration.

                                    "},{"location":"contributing/mkdocs_contributing/#developers-guide-to-trestle-upgrade-commensurate-with-oscal-models-upgrade","title":"Developers Guide to trestle upgrade commensurate with OSCAL models upgrade","text":"

                                    This is a general guide on how to go about upgrading compliance-trestle to support a new version of OSCAL models.

                                    The steps are as follows:

                                    1. Create in GitHub repo (remote)
                                    2. Clone upgrade branch into /trestle-upgrade folder (local <- remote)
                                    3. Download revised and new OSCAL models into folder /trestle-upgrade/release-schemas (local <- remote)
                                      • See https://github.com/usnistgov/OSCAL/releases
                                      • Create & source python virtual environment venv.trestle-upgrade (local)
                                      • Orient current folder to /trestle-upgrade (local)
                                      • Run make develop (local)
                                      • Make necessary code changes:
                                        • Run python scripts/gen_oscal.py (local)
                                        • Run make test-all (local)
                                        • Fix errors and failures via modification of code generation modules and existing trestle modules, as appropriate case-by-case (local)
                                        • Repeat until all errors and failures are fixed (local)
                                        • Run make code-format (local)
                                        • Run make code-lint (local)
                                        • Push /trestle-upgrade folder changes back to GitHub repo (local -> remote)
                                        • Create PR for trestle-upgrade branch -> develop branch (remote)
                                        • Get PR approval (remote)
                                        • Merge PR into develop branch (remote)
                                        • Create PR for develop branch -> main branch (remote)
                                        • Create breaking change (remote)
                                        • Get PR approval (remote)
                                        • Merge develop branch into main branch (remote)"},{"location":"contributing/mkdocs_contributing/#overview-of-process-to-take-oscal-models-and-upgrade-trestle-python-code","title":"Overview of process to take OSCAL models and upgrade trestle Python code","text":""},{"location":"contributing/plugins/","title":"Adding plugins to trestle","text":"

                                          Trestle provides a mechanism for 3rd party providers to extend its command interface via a plugin architecture. All trestle plugins that conforms to this specification will be automatically discovered by trestle if installed, and their command(s) will be added to trestle sub-commands list. Below we describe this plugin mechanism with the help of an example plugin compliance-trestle-fedramp that we created as a separate python project that can be installed via pip.

                                          "},{"location":"contributing/plugins/#create-the-trestle-plugin-proejct","title":"Create the trestle plugin proejct","text":"

                                          A separate plugin project needs to be created that will conatin the code for plugin and its commands. This plugin can be given any name and should be available for installation via pip. For example, we created a plugin project called compliance-trestle-fedramp which can be installed as pip install compliance-trestle-fedramp. The project name doesn't need to start with compliance-trestle.

                                          "},{"location":"contributing/plugins/#project-organization","title":"Project Organization","text":"

                                          The plugin project should be organized as shown below.

                                          compliance-trestle-fedramp\n\u251c\u2500\u2500 trestle_fedramp\n\u2502   \u251c\u2500\u2500 __init.py__\n\u2502   \u251c\u2500\u2500 commands\n|   |   \u251c\u2500\u2500 __init.py__\n|   |   \u251c\u2500\u2500 validate.py\n\u2502   \u251c\u2500\u2500 <other source files or folder>\n\u251c\u2500\u2500 <other files or folder>\n

                                          Trestle uses a naming convention to discover the top-level module of the plugin projects. It expects the top-level module to be named trestle_{plugin_name}. This covention must be followed by plugins to be discoverable by trestle. In the above example, the top-level module is named as trestle_fedramp so that it can be autmatically discovered by trestle. All the python source files should be created inside this module (folder).

                                          The top-evel module should contain a commands directory where all the plugin command files should be stored. Each command should have its own python file. In the above exaample, validate.py file conatins one command for this plugin. Other python files or folders should be created in the top-level module folder, outside the commands folder. This helps in keeping the commands separate and in their discovery by trestle.

                                          "},{"location":"contributing/plugins/#command-creation","title":"Command Creation","text":"

                                          The plugin command should be created as shown in the below code snippet.

                                          from trestle.core.commands.command_docs import CommandBase\nfrom trestle.core.commands.command_docs import CommandPlusDocs\n\nclass ValidateCmd(CommandBase):\n\"\"\"Validate contents of an OSCAL model based on FedRAMP specifications.\"\"\"\n\n    name = 'fedramp-validate'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument('-f', '--file', help='OSCAL file to validate.', type=str, required=True)\n\n        self.add_argument(\n            '-o', '--output-dir', help='Output directory for validation results.', type=str, required=True\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        model_file = pathlib.Path(args.file).resolve()\n\n        output_dir = pathlib.Path(args.output_dir).resolve()\n        ...\n        ...\n        return 0 if valid else 1\n

                                          There should be a command class for example, ValidateCmd which should either extend from CommandBase or CommandPlusDocs. Trestle uses ilcli package to create commands. CommandBase extends from ilcli.Command that initializes the command including help messages and input parameters. CommandPlusDocs in turn extends from CommandBase. The difference between CommandBase and CommandPLusDocs is that CommandBase does not require command line parameter trestle-root to be set or the current directory to be a valid trestle root, whereas CommandPlusDocs requires a valid trestle-root and checks for it. Hence, depending upon the requirement of the plugin command it can extend from either of these classes.

                                          The docstring of the command class is used as the help message for the command. Input arguments to the command should be specified in _init_arguments method as shown above. The acutal code of the command is contained in_run method. This method is called by ilcli when the command is excuted on the commandline. The command arguments can be accessed from the args input parameter as shown above. The command should return 0 in case of successful execution, or any number greater than 0 in case of failure. Please see trestle.core.commands.common.return_codes.CmdReturnCodes class for specific return codes in case of failure.

                                          The command class should conatin the name field which should be set to the desired command name. In the above example, the command is called fedramp-validate. This name is automatically added to the list of sub-command names of trestle during the plugin discovery process. This command can then be invoked as trestle {name} from the commandline e.g., trestle fedramp-validate. Any input parameters to the command can also be passed on the commandline after the command name.

                                          "},{"location":"contributing/trestle_oscal_object_model/","title":"Using trestle as an object model for OSCAL","text":"

                                          Trestle provides an object model for OSCAL to ease the development and validation of OSCAL objects that reside in the trestle.oscal module. This functionality, which is built on pydantic and python data classes, allows validation of the OSCAL schema and is leveraged to provide a variety of utility functions including:

                                          • IO Support for yaml / json / python dict serialisation see OscalBaseModel for trestle enhancements
                                          • The ability to generate pro-forma objects using trestle.core.generate::generate_sample_model
                                          • Integration into the flask api framework (demo)
                                          "},{"location":"contributing/trestle_oscal_object_model/#mapping-and-variance-with-oscal-names","title":"Mapping and variance with OSCAL names.","text":"

                                          The underlying object model that trestle relies on is the json schema published by NIST here. In understanding these models the model reference page is an indispensable source.

                                          When generating the python data class based models we have tried to be as faithful as we can to the naming convention provided by OSCAL. This is the hierarchy of rules that we have used:

                                          1. Do not include prepends from the json schema (e.g. assembly_oscal-catalog_catalog becomes the short name catalog), modules are used for scoping statements
                                          2. OSCAL modules use hyphen case (e.g. system-security-plan) and this is converted to CamelCase (e.g. SystemSecurityPlan)
                                          3. Name collisions with reserved words in python are post-pended with an underscore (e.g. class becomes class_)
                                          4. If a model is used across multiple OSCAL schemas (e.g. metadata) it is put into the common module(trestle.oscal.common), otherwise it will be scoped to a model specifically for that schema.
                                          5. Any unresolved duplicates are resolved by adding an index e.g. class State1
                                          "},{"location":"contributing/trestle_oscal_object_model/#oscal-schema-mapping","title":"OSCAL Schema mapping","text":"

                                          This maps between OSCAL values and the corresponding pydantic/python data class in trestle. For example, to get a catalog you would call:

                                          from pathlib import Path\nfrom trestle.oscal.catalog import Catalog\n\nmy_catalog = Catalog.oscal_read(Path('path/to/file.json'))\n
                                          Oscal schema json schema name Trestle module Trestle class name Catalog catalog catalog trestle.oscal.catalog Profile profile profile trestle.oscal.profile Component Definition component-definition trestle.oscal.component ComponentDefinition System Security Plan system-security-plan trestle.oscal.ssp SystemSecurityPlan Assessment Plan assessment-plan trestle.oscal.assessment_plan AssessmentPlan Assessment Results assessment-results trestle.oscal.assessment_results AssessmentResults Plan of action and milestones plan-of-action-and-milestones trestle.oscal.poam PlanOfActionAndMilestones"},{"location":"contributing/website/","title":"Developing for the trestle documentation website","text":"

                                          This page describes the developing for the trestle (website) which is deployed at https://oscal-compass.github.io/compliance-trestle.

                                          "},{"location":"contributing/website/#documentation-for-use-within-the-github-project","title":"Documentation for use within the github project.","text":"

                                          Github uses certain files within a project such as /README.md, /CONTRIBUTING.md, LICENSE which are specifically indexed by github. The current documentation website build reuses some of these files, specifically:

                                          • Contents of README.md
                                          • Entirety of LICENSE
                                          • Entirety of CONTRIBUTING.md
                                          • Entirety of CODE_OF_CONDUCT.md
                                          • Entirety of CHANGELOG.md
                                          • Entirely of MAINTAINERS.md
                                          • Entirely of DCO1.1.txt

                                          For this to work correctly no relative links within the github repository should exist. All links should be absolute to the documentation website.

                                          "},{"location":"contributing/website/#build-system-and-local-testing-of-the-website","title":"Build system and local testing of the website.","text":"

                                          Trestle has adopted the mkdocs system to generate this website using a small number of extensions to mkdocs. The website can be viewed locally from a clone of the compliance-trestle repo by running make docs-serve in the root directory bringing the website up at https://localhost:8000. If you experience issues run make develop to ensure the appropriate markdown extensions are in your python environment.

                                          make docs-serve performs two actions:

                                          • Runs the custom automation script scripts/website_automation.py
                                          • Serves the website on localhost.

                                          All documentation specific assets are stored within the ./docs folder. The exception being mkdocs.yml which configures the documentation tree. Before opening a PR users should ensure:

                                          • No warnings are generated by mkdocs
                                          • All markdown documents within ./docs are included in the website navigation defined in mkdocs.yml
                                          "},{"location":"contributing/website/#trestle-custom-automation","title":"trestle custom automation.","text":"

                                          In order to streamline development, and ensure the website remains up to date, a small automation script has been built. This automation script principally ensures that:

                                          • License is consistent with github.com
                                          • All modules are in the reference documentation

                                          running make docs-automation will ensure that the website is ready to deploy.

                                          "},{"location":"contributing/website/#building-the-models-from-the-oscal-schemas","title":"Building the models from the OSCAL schemas.","text":"

                                          The creation of the OSCAL models in trestle/oscal is a multi-step process:

                                          • The oscal schemas are downloaded as modules from NIST into the nist-source/json/schema directory.
                                          • The script scripts/gen-oscal.py loads each schema file and converts it to pydantic/python with datamodel-codegen.
                                          • The generated python files may need some fixup, so a separate script scripts/fix_any.py is run on each file.
                                          • Note that there is one schema specific to IBM needs and it is loaded from 3rd-party-schema-documents/IBM_target_schema_v1.0.0.json.

                                          The whole process is handled in the Makefile by make code-gen. A normal user would never need to run this but developers may need to, particularly if there are changes to the OSCAL schemas.

                                          Also note that the depenedent tools, pydantic and datamodel-codegen, may get updated by doing a fresh make install or make develop, which may then result in a change to the model files.

                                          "},{"location":"contributing/website/#items-handled-by-fix_anypy","title":"Items handled by fix_any.py.","text":"

                                          The original motivation for this script was to replace numerous situations where the type assigned to a given variable was simply Any, which meant no type enforcement would apply for that variable, defeating the purpose of the strict type enforcement provided by Pydantic. As of this writing the number of such cases has been reduced to just one - which is handled by the script.

                                          Other issues handled by the script are:

                                          • The current OSCAL schemas have situations where objects are defined within different classes in a schema using the same name, but the contents of those classes may or may not be different. datamodel-codegen handles this by creating separate classes as needed and appending 1, 2 etc. to the names, keeping them distinct. The resulting high level classes that reference them behave as expected, but if components of those classes are added in a granular way by a user or developer, the correct index must be used.
                                          • To reduce side-effects of the duplicate classes, classes are checked to see if they are identical or not. If they are identical the separate 1, 2 classes are culled and references to them are pointed to the non-indexed class.
                                          • Currently there are 5 classes that require a separate '1' version: Status, Type, Entry, LocalDefinitions, and Action.
                                          • In order to guarantee there are no induced forward references in the files, the classes are reordered to minimize the need for forwards, and any that can't be avoided are explicitly provided at the bottom of the file.
                                          • The generated files have many classes that simply have a __root__ element defined, along with a description. Such classes don't have particular value in such a simple form and could instead simply be defined in the parent class.
                                          "},{"location":"contributing/website/#seeing-the-changes-induced-by-fix_anypy-on-the-classes","title":"Seeing the changes induced by fix_any.py on the classes.","text":"

                                          As a convenience for developers, a separate script, scripts/order_classes.py is available, which orders the classes in a given file alphabetically. This way, if you use the script on files before and after applying fix_any.py you can use a normal diff tool to see the changes made. This is strictly as a development tool for doing the comparison and the resulting files will not work since they will have forward references.

                                          "},{"location":"plugins/compliance-trestle-fedramp/","title":"compliance-trestle-fedramp plugin","text":"

                                          This plugin provides functionality for validating an SSP for FedRAMP compliance. It provides both an API interface and a trestle command for performing this validation.

                                          "},{"location":"plugins/compliance-trestle-fedramp/#trestle-fedramp-validate","title":"trestle fedramp-validate","text":"

                                          This command allows users to validate existing OSCAL SSP file (in JSON or YAML format) for FedRAMP compliance. For example, trestle fedramp-validate -f /local_dir/ssp.json -o report/ will validate ssp.json file for fedramp complaince and store the validation reports in report folder.

                                          The following options are supported:

                                          • -f or --file: specifies the path of an existing OSCAL SSP file. It may be an absolute or relative path. The file must be in either JSON or YAML format. This is a required option.
                                          • -o or --output: specifies the name of the output directory where the validation reports will be stored. It may be an absolute or relative path. The output directory should already exist. This is also a required option.

                                          The validation reports are created in XML and HTML format and provide details on which part of the SSP are not complaint as per FedRAMP specification.

                                          "},{"location":"reference/third-party-result-schema-SCC/","title":"Schema of Assessment Results for Interchange with IBM Cloud Security and Compliance Center, SCC","text":"

                                          This document depicts the structure and guidelines for creating an OSCAL result object which would be generated by various transformers for different tools such as Tanium to OSCAL and OSCO to OSCAL. Policy Validation Points (PVPs) such as toolchain that directly generate OSCAL results for sending to SCC Exchange API should follow the structure and guidelines described below.

                                          The overall object will be a results element of OSCAL Assessment Result schema wrapped in an outer json object as shown below.

                                          {\n\"results\": [\n{\n\"result\": \"object\"\n},\n{\n\"result\": \"object\"\n}\n]\n}\n

                                          Each result object represents one assessment scan and should have the required properties as per OSCAL schema. The start and end represents the start and end datetime of evidence collection activity. The end is optional. In addition to these, the result object may contain details about inventory, list of observations (checks) for each inventory, and findings for profile level controls (such as NIST).

                                          {\n\"uuid\": \"cd54e9bf-f4d3-45d6-ae3b-6e8255847dc2\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-04-05T20:19:11.000+00:00\",\n\"end\": \"2021-04-05T20:19:11.000+00:00\",\n\"local-definitions\": {},\n\"reviewed-controls\": {},\n\"observations\": {},\n\"findings\": {}\n}\n

                                          The inventory should be included in local-definitions if observations are being reported, but can be omitted if only findings are being reported. As reviewed-controls is required as per OSCAL schema, an empty object should be included if only observations are being reported. Optionally, the controls for which the status is being reported in findings can be captured here. The actual assessment checks being performed on different inventory items should be captured under observations. This can be omitted if only findings are being reported. As findings is required as per OSCAL schema, an empty object can be included if only observations are being reported and no profile controls are being assessed. Otherwise, findings should include the status of profile controls.

                                          "},{"location":"reference/third-party-result-schema-SCC/#general-guidance","title":"General Guidance","text":"
                                          1. All the properties in the source result (tool specific format) should be represented as properties of the right objects in OSCAL such as inventory-items, observations, etc. The properties should have a tool specific namespace to convey that the property names are exactly same as what is coming from specific tools.

                                          2. Not everything from the non-OSCAL results are relevant (required) by SCC. The relevant properties MUST have SCC specific class such as scc_inventory_item_id, scc_result, etc. This will help SCC identify corresponding information from different tools and handle them appropriately. SCC MUST store the original property names so that when these are retrieved by tools later, they can get back the same name-value pairs as was there in the input data.

                                          3. There must be a pre-defined set of properties (class values) from SCC for each result object component such as inventory-items, components, observations, etc.

                                          4. A property value MUST be a string of appropriate format.

                                          "},{"location":"reference/third-party-result-schema-SCC/#transforms","title":"Transforms","text":"
                                          1. File Unification SCC class for OSCO and Tanium to OSCAL.xlsx contains the SCC class mapping from Tanium and OpenShift Compliance Operator results data to OSCAL. Although other properties are constructed during transformation, only items having SCC class are shown in the table.
                                          "},{"location":"reference/third-party-result-schema-SCC/#inventory","title":"Inventory","text":"
                                          1. Inventory is captured under local-definitions in result object. local-definitions can be used to represent inventory items, components, users, etc. For our purposes only components and inventory-items will be used. Components should be used to represent software, services, etc. whereas inventory-items represent specific machines, VMs, network devices, etc. The inventory items should be associated to a component through implemented-components as shown below.
                                          {\n\"local-definitions\": {\n\"components\": {\n\"b3e243a1-4660-4f5a-aa85-159b4b2d69ce\": {\n\"type\": \"Operating System\",\n\"title\": \"Windows 10\",\n\"description\": \"Windows 10\",\n\"status\": {\n\"state\": \"operational\"\n}\n}\n},\n\"inventory-items\": [\n{\n\"uuid\": \"c9fb63cf-d21e-4584-88f8-44d67ea33ba0\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"Computer Name\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"cmp-wn-2106.demo.tanium.local\"\n},\n{\n\"name\": \"Tanium Client IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"192.168.0.120\",\n\"class\": \"scc_inventory_item_id\"\n},\n{\n\"name\": \"IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"['fe80::cd44:4154:61e8:53ae', '192.168.0.120']\"\n},\n{\n\"name\": \"Count\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1\"\n}\n],\n\"implemented-components\": [\n{\n\"component-uuid\": \"b3e243a1-4660-4f5a-aa85-159b4b2d69ce\"\n}\n]\n}\n]\n}\n}\n
                                          1. Inventory items have one required property with class scc_inventory_item_id as shown above. Similarly in some other tool's result the scc_inventory_item_id may be specified through some other property. It is the job of the transformation code to appropriately specify class values for required properties. As shown above, non-mandatory property such as count from native result does not have any class specified.

                                          2. The type of the inventory item is specified by linking it to component via implemented-components.

                                          "},{"location":"reference/third-party-result-schema-SCC/#observation","title":"Observation","text":"
                                          1. Loosely speaking, an observation object equates with results from a goal check, and the observation is uniquely identified by a uuid, e.g.,
                                          {\n\"uuid\": \"00000000-0000-4000-9999-000000000016\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\"\n}\n
                                          1. A sample observation object generated from Tanium result looks like -
                                          {\n\"uuid\": \"74b605f8-7e8c-41b3-9514-2412692fbe01\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-11T22:34:03+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"c8919d2b-3300-4f3f-98f6-15a7104c2e04\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-11T22:34:03.000+00:00\"\n}\n
                                          1. An observation has five required properties -

                                          2. scc_predefined_profile - identifies both Goal based Profiles (eg CIS-benchmarks, IBM BP etc) and Control/Regulation based Profiles (eg. NIST, FS Cloud etc). The way the integrators or customers will differentiate between the two types of profiles is by the OSCAL element used i.e., Goal based Profiles are defined in the observation element which carries the goal id (check id) and posture. Control/Regulation based Profiles\u00a0 are defined in the finding element which carries the control posture, the custom profile name, and the mapping of the goal results to NIST controls

                                          3. scc_check_version, scc_predefined_profile_version - gives the version of the goal/profile i.e., CIS benchmark version used for check.
                                          4. scc_goal_description, scc_check_name_id - gives the specific goal check (rule) that was assessed from the scc_predefined_profile.
                                          5. scc_result - gives the outcome of performing the check. Possible values are - \"pass\", \"fail\", \"error\" , \"unknown\", \"notchecked\", \"notapplicable\".
                                          6. scc_timestamp - datetime for this observation. This can be date and time when this observation was performed or reported.

                                          7. Targets such as systems or services MUST be a subject in the observation, which MUST be identified by a uuid-ref value pointing to the subject in local-definitions.

                                          "},{"location":"reference/third-party-result-schema-SCC/#finding","title":"Finding","text":"
                                          1. A finding represents the assessment of a profile control such as NIST 800-53: AC-1 and the related observations. A sample finding object looks like -
                                          {\n\"uuid\": \"cde35fad-3922-4046-8ef8-830e77ffd75a\",\n\"title\": \"800-53: IA-5\",\n\"description\": \"800-53: IA-5\",\n\"target\": {\n\"type\": \"statement-id\",\n\"id-ref\": \"800-53: IA-5\",\n\"props\": [\n{\n\"name\": \"Profile\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Windows 10 - NIST 800-53\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"version: 1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Custom ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"800-53: IA-5\"\n}\n],\n\"status\": \"not-satisfied\"\n},\n\"related-observations\": [\n{\n\"observation-uuid\": \"d8bd1785-b95f-45c9-9fa8-32a362845102\"\n},\n{\n\"observation-uuid\": \"d06c6f13-5006-4e2d-b3f3-5cdb577473b1\"\n}\n]\n}\n
                                          1. A finding has two required property scc_predefined_profile that gives the name of the profile whose control is specified in \"id-ref\", and scc_predefined_profile_version.

                                          2. If there is no finding associated with a PVP, a single finding will be created (to preserve valid OSCAL) where the UUID maps to a 'all zeros' UUID e.g.:

                                          {\n\"uuid\": \"00000000-0000-4000-8000-000000000000\",\n\"title\": \"No finding\",\n\"description\": \"No finding.\"\n}\n
                                          "},{"location":"tutorials/trestle_sample_workflow/","title":"Tutorial: Introduction to trestle workflow","text":"

                                          Here are step-by-step instructions to manipulate a NIST standard OSCAL catalog using the compliance-trestle (\"trestle\") tool.

                                          "},{"location":"tutorials/trestle_sample_workflow/#objective","title":"Objective","text":"

                                          Learn how to split and merge an OSCAL catalog json file using trestle commands and its command line interface (CLI). Trestle simplifies the manipulation and management of large OSCAL documents by allowing controlled deconstruction into smaller components, and later reconstruction after editing those components. And all operations guarantee that the individual files conform to the corresponding OSCAL schema to maintain integrity of the document in the process.

                                          This tutorial assumes you have installed Python and installed trestle in a virtual environment per the directions found here.

                                          The examples shown will work for linux and mac, but Windows will require the following modifications:

                                          • use backslashes `\\` for file paths (this is optional in most cases)
                                          • use copy instead of cp (unless you have cp installed)
                                          • use md instead of mkdir (unless you have mkdir installed)
                                          • quotes (') are often not needed unless the text includes spaces, but if quotes are needed they should be double quotes (\")

                                            Commands are shown without prompts so they are easy to cut and paste, and responses by trestle are shown with >>> at the start of the line. In actual usage the >>> would not appear.

                                            Be sure to include the quotes (' ') as shown in the examples, e.g. merge -e 'catalog.*' [On windows you should probably use double quotes (\") as needed.]

                                            In this tutorial you will see sections that contain dropdown that is revealed when you click on them. Below is an example (\"Like this\"). Be sure to click on those sections to see their contents - and then close them if you like.

                                            Like this
                                            more\ninformation\nin\nhere\n

                                            "},{"location":"tutorials/trestle_sample_workflow/#step-1-create-a-trestle-workspace-if-you-dont-have-one-already","title":"Step 1: Create a trestle workspace if you don't have one already","text":"
                                            mkdir my_workspace\ncd my_workspace\ntrestle init\n>>> Initialized trestle project successfully in [user_path]/my_workspace\n
                                            "},{"location":"tutorials/trestle_sample_workflow/#step-2-import-a-catalog-from-the-trestle-sample-data-directory-into-your-trestle-workspace","title":"Step 2: Import a catalog from the trestle sample data directory into your trestle workspace","text":"

                                            For this tutorial we will use a catalog file from NIST, but we first must import it into the trestle workspace. This can be done either by first downloading the file locally and then importing it, or you can download it directly using its url address.

                                            We will import the file directly from the NIST OSCAL github site. The specific catalog is NIST_SP-800-53_rev5_catalog.json

                                            Import the file from the url with the following command:

                                            trestle import -f https://raw.githubusercontent.com/usnistgov/oscal-content/master/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_catalog.json -o mycatalog\n

                                            As a reminder, you could also have imported the file from a local directory on your file system, or an sftp:// address. But the file must first be imported to the trestle workspace in order for it to be directly manipulated by trestle as in this tutorial.

                                            The import command will also check the validity of the file including the presence of any duplicate uuid's. If the file is manually created please be sure it conforms with the current OSCAL schema (OSCAL version 1.0.4) and has no defined uuid's that are duplicates. If there are any errors the Import will fail and the file must be corrected.

                                            Your initial workspace will look like this
                                            my_workspace\n \u2523 .trestle\n \u2503 \u2523 .keep\n \u2503 \u2517 config.ini\n \u2523 assessment-plans\n \u2503 \u2517 .keep\n \u2523 assessment-results\n \u2503 \u2517 .keep\n \u2523 catalogs\n \u2503 \u2523 mycatalog\n \u2503 \u2503 \u2517 catalog.json\n \u2503 \u2517 .keep\n \u2523 component-definitions\n \u2503 \u2517 .keep\n \u2523 dist\n \u2503 \u2523 assessment-plans\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 assessment-results\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 catalogs\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 component-definitions\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 plan-of-action-and-milestones\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 profiles\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 system-security-plans\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2517 target-definitions\n \u2503 \u2503 \u2517 .keep\n \u2523 plan-of-action-and-milestones\n \u2503 \u2517 .keep\n \u2523 profiles\n \u2503 \u2517 .keep\n \u2523 system-security-plans\n \u2503 \u2517 .keep\n \u2517 target-definitions\n \u2503 \u2517 .keep\n

                                            You will see that the directory now shows your catalog file in my_workspace/catalogs/mycatalog/catalog.json. Note that the .keep files are simply to make sure git does not remove the directories - and can be ignored. Also note that the json file itself is singular (catalog) while the directory above is plural (catalogs). This convention is used throughout trestle because a given model directory like catalogs may contain several individual models - each of which is singular. The imported catalog file size may be larger than the original due to a change in formatting, but the contents should be the same.

                                            From here on in this tutorial we will just focus on the catalogs directory since the others are not directly involved.

                                            You have now populated your trestle workspace with an OSCAL catalog that you can manipulate. Let's start.

                                            "},{"location":"tutorials/trestle_sample_workflow/#step-3-split-the-file-into-smaller-parts","title":"Step 3: Split the file into smaller parts","text":"

                                            The OSCAL schema specifies that a catalog must contain metadata, groups, and back-matter - so this command will pull them out of the original file and place them in separate json files for additional manipulations.

                                            To begin splitting the file, first cd to the directory where catalog.json has been placed.

                                            cd catalogs/mycatalog\ntrestle split -f ./catalog.json -e 'catalog.metadata,catalog.groups,catalog.back-matter'\n

                                            Here the -f refers to the filename of the json catalog file, and -e refers to the comma-separated list of elements you would like to split from the file. This list does not represent the full file contents of the source catalog.json file, so some contents will be left behind in a much smaller catalog.json file after the split. The elements that were split off will be placed in separate json files next to the new and smaller catalog.json file.

                                            Your new catalogs directory with json files split out
                                            catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                            Note there still remains a catalog.json file, but it is much smaller since the bulk of its contents have been split off.

                                            Any split step can be reversed by a corresponding merge operation. In this case we can go backwards with:

                                            trestle merge -e 'catalog.metadata,catalog.groups,catalog.back-matter'\n

                                            or simply

                                            trestle merge -e 'catalog.*'\n

                                            You can go back and forth splitting and merging, but for the next step please start with the above files split so that metadata.json can be further split.

                                            "},{"location":"tutorials/trestle_sample_workflow/#step-4-split-the-metadata-into-constituent-files","title":"Step 4: Split the metadata into constituent files","text":"
                                            cd catalog\ntrestle split -f ./metadata.json -e 'metadata.roles,metadata.parties,metadata.responsible-parties'\n
                                            The directory will now look like this, with metadata split into files
                                            catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2523 parties.json\n \u2503 \u2503 \u2503 \u2523 responsible-parties.json\n \u2503 \u2503 \u2503 \u2517 roles.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                            Again there remains a metadata.json file but it is smaller than the original.

                                            And this step can be reversed with the following:

                                            trestle merge -e 'metadata.roles,metadata.parties,metadata.responsible-parties'\n

                                            or simply

                                            trestle merge -e 'metadata.*'\n
                                            "},{"location":"tutorials/trestle_sample_workflow/#step-5-split-metadata-further-using-wildcards","title":"Step 5: Split metadata further using wildcards","text":"
                                            cd metadata\ntrestle split -f ./roles.json -e 'roles.*'\ntrestle split -f ./responsible-parties.json -e 'responsible-parties.*'\n
                                            The directory now looks like this, with new subdirectories containing multiple roles and responsible-parties
                                            catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2523 responsible-parties\n \u2503 \u2503 \u2503 \u2503 \u2523 contact__responsible-party.json\n \u2503 \u2503 \u2503 \u2503 \u2517 creator__responsible-party.json\n \u2503 \u2503 \u2503 \u2523 roles\n \u2503 \u2503 \u2503 \u2503 \u2523 00000__role.json\n \u2503 \u2503 \u2503 \u2503 \u2517 00001__role.json\n \u2503 \u2503 \u2503 \u2517 parties.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                            Note that the presence of wildcards caused new directories to be created containing the full lists of roles and responsible parties. You can read the wildcard as split off all roles from roles.json.

                                            This split can be reversed with

                                            trestle merge -e 'roles.*,responsible-parties.*'\n
                                            "},{"location":"tutorials/trestle_sample_workflow/#step-6-split-groups-and-controls-with-two-wildcards","title":"Step 6: Split groups and controls with two wildcards","text":"

                                            This single command will split off all controls in all groups. To do it you need to go back up into the catalog directory where the groups.json file is found:

                                            cd ..\ntrestle split -f ./groups.json -e 'groups.*.controls.*'\n

                                            Your directory is now very large with that one command!
                                            catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 groups\n \u2503 \u2503 \u2503 \u2523 00000__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00022__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00023__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00024__control.json\n \u2503 \u2503 \u2503 \u2523 00001__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00005__control.json\n \u2503 \u2503 \u2503 \u2523 00002__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00015__control.json\n \u2503 \u2503 \u2503 \u2523 00003__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00008__control.json\n \u2503 \u2503 \u2503 \u2523 00004__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00013__control.json\n \u2503 \u2503 \u2503 \u2523 00005__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00012__control.json\n \u2503 \u2503 \u2503 \u2523 00006__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00011__control.json\n \u2503 \u2503 \u2503 \u2523 00007__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00009__control.json\n \u2503 \u2503 \u2503 \u2523 00008__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00006__control.json\n \u2503 \u2503 \u2503 \u2523 00009__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00007__control.json\n \u2503 \u2503 \u2503 \u2523 00010__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00022__control.json\n \u2503 \u2503 \u2503 \u2523 00011__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00010__control.json\n \u2503 \u2503 \u2503 \u2523 00012__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00022__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00023__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00024__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00025__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00026__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00027__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00028__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00029__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00030__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00031__control.json\n \u2503 \u2503 \u2503 \u2523 00013__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00008__control.json\n \u2503 \u2503 \u2503 \u2523 00014__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00007__control.json\n \u2503 \u2503 \u2503 \u2523 00015__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00009__control.json\n \u2503 \u2503 \u2503 \u2523 00016__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00022__control.json\n \u2503 \u2503 \u2503 \u2523 00017__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00022__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00023__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00024__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00025__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00026__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00027__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00028__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00029__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00030__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00031__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00032__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00033__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00034__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00035__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00036__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00037__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00038__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00039__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00040__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00041__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00042__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00043__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00044__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00045__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00046__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00047__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00048__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00049__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00050__control.json\n \u2503 \u2503 \u2503 \u2523 00018__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00022__control.json\n \u2503 \u2503 \u2503 \u2523 00019__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00011__control.json\n \u2503 \u2503 \u2503 \u2523 00000__group.json\n \u2503 \u2503 \u2503 \u2523 00001__group.json\n \u2503 \u2503 \u2503 \u2523 00002__group.json\n \u2503 \u2503 \u2503 \u2523 00003__group.json\n \u2503 \u2503 \u2503 \u2523 00004__group.json\n \u2503 \u2503 \u2503 \u2523 00005__group.json\n \u2503 \u2503 \u2503 \u2523 00006__group.json\n \u2503 \u2503 \u2503 \u2523 00007__group.json\n \u2503 \u2503 \u2503 \u2523 00008__group.json\n \u2503 \u2503 \u2503 \u2523 00009__group.json\n \u2503 \u2503 \u2503 \u2523 00010__group.json\n \u2503 \u2503 \u2503 \u2523 00011__group.json\n \u2503 \u2503 \u2503 \u2523 00012__group.json\n \u2503 \u2503 \u2503 \u2523 00013__group.json\n \u2503 \u2503 \u2503 \u2523 00014__group.json\n \u2503 \u2503 \u2503 \u2523 00015__group.json\n \u2503 \u2503 \u2503 \u2523 00016__group.json\n \u2503 \u2503 \u2503 \u2523 00017__group.json\n \u2503 \u2503 \u2503 \u2523 00018__group.json\n \u2503 \u2503 \u2503 \u2517 00019__group.json\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2523 responsible-parties\n \u2503 \u2503 \u2503 \u2503 \u2523 contact__responsible-party.json\n \u2503 \u2503 \u2503 \u2503 \u2517 creator__responsible-party.json\n \u2503 \u2503 \u2503 \u2523 roles\n \u2503 \u2503 \u2503 \u2503 \u2523 00000__role.json\n \u2503 \u2503 \u2503 \u2503 \u2517 00001__role.json\n \u2503 \u2503 \u2503 \u2517 parties.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                            All 20 groups of controls have been split off, and each one has a corresponding directory with its full list of controls in it.

                                            You can then reverse the split with

                                            trestle merge -e 'groups.*'\n
                                            "},{"location":"tutorials/trestle_sample_workflow/#step-7-collapse-the-entire-directory-structure-back-into-a-single-catalogjson-file-possibly-after-modifying-individual-files","title":"Step 7: Collapse the entire directory structure back into a single catalog.json file - possibly after modifying individual files","text":"

                                            You can collapse everything back to a single catalog.json file after first going up one directory to the mycatalog directory

                                            cd ..\ntrestle merge -e 'catalog.*'\n

                                            After all that splitting and merging you are back to this directory structure
                                            catalogs\n \u2517 mycatalog\n \u2503 \u2517 catalog.json\n

                                            "},{"location":"tutorials/trestle_sample_workflow/#conclusion","title":"Conclusion","text":"

                                            This completes the tutorial on using trestle to split and merge an OSCAL catalog file. Not shown here are modifications of the individual files that would be done in an actual use case, but note that if any changes are made that violate the OSCAL schema, trestle will notice them and flag them in the merge. This way not only does trestle allow user-driven decomposition and aggregation of these large, complex files; it also does constant checks on the contents against the required schema to make sure no errors are introduced in the process.

                                            "},{"location":"tutorials/continuous-compliance/continuous-compliance/","title":"Tutorial: What\u2019s your compliance posture?","text":""},{"location":"tutorials/continuous-compliance/continuous-compliance/#introduction","title":"Introduction","text":"

                                            The cloud with its continuous integration and continuous deployment is the modern computing paradigm. There is a plethora of cloud environments: public, private, on-premise, hybrid-cloud, multi-cloud, etc. along with a corresponding contingent of vendors. The cloud offers great flexibility where you can choose just one or some combination optimal for each application. But, as demonstrated from time to time, the cloud can be a dangerous place. Hackers, bots, malware, and more are constant threats seeking to find and exploit weakness in your computing solution. To combat them there are strategies to avoid embarrassment and financial ruin from security breeches. Educating your workforce is of paramount importance. Moreover, employing a trust-but-verify strategy will go a long way toward deflecting trouble.

                                            The time has come for continuous auditing, and giving stakeholders (such as account owners, application owners, system owners and compliance officers) a current picture of their compliance posture:

                                            • Are password rules being followed?
                                            • Are deployed applications using compromised encryption algorithms?
                                            • Has a user gotten elevated privileges?
                                            • Are unauthorized open source projects wrongfully part of your application stack?

                                            Getting answers to these questions only quarterly or annually is leaving you exposed.

                                            Moreover, assuring continuous compliance across multiple cloud vendors can complicate matters. If each has its own compliance regime, then one must become expert in each domain\u2019s compliance solution space, or else be wedded to a single or few providers. That is not an ideal prospect.

                                            Common sense dictates that standardization would simplify matters. The National Institute of Standards and Technologies (NIST) is developing the Open Security Controls Assessment Language (OSCAL).

                                            The compliance-trestle open source github project is an effort to employ OSCAL for compliance standardization and automation. Of great utility is the trestle oscal module that facilitates transformation of data to/from Python object representations in accordance with the OSCAL schemas.

                                            "},{"location":"tutorials/continuous-compliance/continuous-compliance/#simple-continuous-compliance-architecture","title":"Simple Continuous Compliance Architecture","text":"

                                            Cloud Services can often be configured to monitor (and sometimes enforce) policies. Examples include OpenShift Compliance Operator and Tanium. However, the compliance reporting \u201craw\u201d data produced is unique to each.

                                            Two steps are needed to ascertain your compliance posture. Step 1 is to transform available compliance \u201craw\u201d data into standardized form (OSCAL). Step 2 is to examine the OSCAL data and assemble a compliance posture for the controls and components of interest. And trestle is the go-to solution.

                                            "},{"location":"tutorials/continuous-compliance/continuous-compliance/#step-1-transformation","title":"Step 1 \u2013 Transformation","text":"

                                            The bad news is that a transformer to OSCAL is needed for each Cloud Service type.

                                            However, there is plenty of good news:

                                            • a transformer for your Cloud Service type may already exist, such as: Tanium to OSCAL, OpenShift Compliance Operator to OSCAL
                                            • once a transformer for a Cloud Service type has been written, it can be open-sourced/re-used
                                            • writing a transformer is fairly easy: just a few lines of Python code using trestle as a foundation

                                            In the case of Tanium, the OSCAL compliance data document is a System Assessment Results fragment with Findings and Observations, while in the case of OpenShift Compliance Operator there are Observations only.

                                            Tutorials are available to show you: how to run a transformer, how to write a transformer.

                                            "},{"location":"tutorials/continuous-compliance/continuous-compliance/#step-2-reporting","title":"Step 2 \u2013 Reporting","text":"

                                            Coming soon is a trestle tool to assemble the OSCAL fragments documents together using OSCAL compliance configuration data (System Assessment Plan and System Security Plan) into a complete System Assessment Results.

                                            "},{"location":"tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/","title":"Tutorial: Catalog, Profile, ComponentDefinition, and SSP Authoring","text":""},{"location":"tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/#introduction-and-background","title":"Introduction and background","text":"

                                            In addition to core functionality for automated processing of OSCAL documents, Trestle has authoring tools that allow conversion of OSCAL documents to markdown for easy editing - and conversion back to OSCAL for validation and automation. A big part of compliance involves writing guidance prose associated with controls, along with the setting of parameters and properties for those controls. This cannot be completely automated because it requires human editing, along with human approvals of those edits. The purpose of the authoring tools is to allow selected edits of oscal documents guided by prompts for where content is required. This serves to streamline the edit/approval process whereby the author is presented with one markdown document per control, and it provides a view of the the key information needed during the editing process. This greatly simplifies the editing process compared to multiple authors working together on a single large JSON document.

                                            The key modes of authoring are -generate and -assemble. During -generate a JSON document is converted to markdown format, allowing authors to add or edit prose and parameter values. After editing, the markdown can then be -assembled into the same or a new JSON document that captures the edit changes. In a normal authoring cycle, the markdown is generated for the first time from a given JSON file, and after that there is a continuous process of editing and reassembling to keep the JSON up to date with the markdown edits.

                                            A third mode of authoring is -filter, where parts of a document are removed. This allows one large master document to be represented in simpler ways with, e.g. proprietary prose culled in form intended for consumption outside a company.

                                            Integration with git and CI/CD

                                            The command line interface in Trestle makes a powerful combination with git and CI/CD environments (Continuous Integration, Continuous Delivery or Deployment) when the trestle commands are performed via github actions or equivalent. This allows different classes of users based on 1) their access to the repository 2) the changes to documents they are allowed to commit, and 3) the changes they can make to actions that are triggered by a commit. As an example, a command line option may limit the type of content added to a profile, and if disallowed changes are detected during commit - the commit will be rejected. This, in combination with having all controls as individual markdown files organized by groups in directories, makes management and tracking of author edits robust and automatically controlled by the built-in features of the respository.

                                            For an example of actions triggered by a commit, a change to a control in a catalog could generate a pull request that is approved by someone with appropriate authority, and when it is later merged it triggers notification downstream to authors of profiles that import that catalog.

                                            The author commands

                                            The author commands are:

                                            1. catalog-generate converts a control Catalog to individual controls in markdown format for addition or editing of guidance prose and parameters, with parameters stored in a yaml header at the top of the markdown file. catalog-assemble then gathers the prose and parameters and updates the controls in the Catalog to make a new OSCAL Catalog.
                                            2. profile-generate takes a given Profile and converts the controls represented by its resolved profile catalog to individual controls in markdown format, with sections corresponding to the content that the Profile adds to the Catalog, along with both the current values of parameters in the resolved profile catalog - and the values that are being modified by the given profile's SetParameters. The user may edit the content or add more, and profile-assemble then gathers the updated content and creates a new OSCAL Profile that includes those changes.
                                            3. profile-resolve is special as an authoring tool because it does not involve markdown and instead it simply creates a JSON resolved profile catalog from a specified JSON profile in the trestle directory. There are options to specify whether or not parameters get replace in the control prose or not, along with any special brackets that might be desired to indicate the parameters embedded in the prose.
                                            4. profile-inherit takes a given parent profile and filters its contents based on the inherited controls included in a given ssp to be include in the final profile.
                                            5. component-generate takes a given ComponentDefinition file and represents all the controls in markdown in separate directories for each Component in the file. This allows editing of the prose on a per-component basis. component-assemble then assembles the markdown for all controls in all component directories into a new, or the same, ComponentDefinition file.
                                            6. ssp-generate takes a given Profile and an optional list of component-definitions, and represents the individual controls as markdown files with sections that prompt for prose regarding the implementation response for items in the statement of the control, with separate response sections for each component. ssp-assemble then gathers the response sections and creates an OSCAL System Security Plan comprising the resolved profile catalog and the implementation responses for each component. The list of component-definitions is optional, but without them the SSP will only have one component: This System. Rules, parameters and status associated with the implemented requirements are stored in the SetParameters and Properties of the components in the component definitions and represented in the markdown, allowing changes to be made to the parameter values and status. These edits are then included in the assembled SSP. Note that the rules themselves may not be edited and strictly correspond to what is in the component definitions.
                                            7. ssp-filter takes a given ssp and filters its contents based on the controls included in a provided profile, or in a list of components to be included in the final ssp.

                                            In summary, the catalog tools allow conversion of a Catalog to markdown for editing - and back again to a Catalog. The profile tools similarly convert a Profile's resolved profile catalog to markdown and allow conversion to a new Profile with modified additions that get applied in resolving the profile catalog. component tools perform similarly for ComponentDefinitions. Finally, the ssp tools allow the addition of implementation prose to the markdown of a system security plan, which is then assembled into a JSON SSP on a by-component basis.

                                            Note that the original ssp implementation in trestle created SSP's by adding prose directly to the SSP markdown on a per-component basis, and there was no connection with separate ComponentDefinition JSON files. This is now changed so that control responses can be added to the ComponentDefinition and then merged to create the SSP markdown. In addition, rules and status are captured in the component definition as properties that propogate via markdown into the assembled SSP. The OSCAL schema doesn't include a form of implementation status for components in the component definition, which is why trestle embeds the status value in the properties. Similarly, rules and rule parameter values are not currently part of the schema, so they are also embedded in properties.

                                            Some details of the author commands

                                            The markdown files for controls usually have a YAML header at the top containing metadata about the control. Sometimes that information is read-only and intended as additional information useful during markdown editing, but in other cases the content may be edited and incorporated as new values for the control after -assemble. In addition, most -generate commands allow specifying a separate YAML header file containing information either needed by the command, or intended to be incorporated into the header of each control markdown file. When generating markdown a YAML header may be optionally provided, and if so, the option --overwrite-header-values will cause the values in the provided YAML header to overwrite the value in the markdown file's header for any items that are common. Otherwise the provided YAML header will simply insert any values not already in the markdown header. By default, Trestle will preserve the history of the changes in generated markdowns, however --force-overwrite option can be used to overwrite markdowns with content from JSON. Note that this option will completely delete all existing markdowns (in the given output folder) without saving any changes. To save the changes, run assemble first. Similarly, when assembling to JSON, the --set-parameters option will cause any changes in the header to take effect and change values in the assembled JSON for the control. The changes can including setting parameter and property values. The --set-parameters option is available only for catalog-assemble and profile-assemble.

                                            As described earlier, the authoring tools are designed to work well in a CI/CD environment where changes are made in a pipeline by people with different responsibilities and authority. In this setting, changes to documents can trigger changes downstream, e.g. the editing of a control would cause an update in the catalog, which could then flow down to an updated SSP. These changes can occur automatically via actions that restrict the potential changes to the generated documents. Examples are the --set-parameters option on the -assemble tools, and both --required-sections and allowed-sections for profile-assemble. If a document change triggers an assemble action, changes to parameters can only occur if the action has --set-parameters in the command. Similarly, profile-assemble will fail if the sections do not meet the requirements specified in the command options. Another feature of the -assemble tools is that they won't create a new OSCAL file if the output already exists and its content would not be changed. This prevents undesired triggering of downstream actions when there is no actual change in content.

                                            There is a standalone demonstration of the SSP generation process with trestle in the Trestle SSP Demo that captures the entire process of SSP authoring: from creation of a component definition from CSV file to a final formatted system security plan in Word (.docx) format.

                                            Background on underlying concepts

                                            In order to understand the specific operations handled by these commands, it is helpful to clarify some of the underlying OSCAL structures and how they can be edited in markdown form. This tutorial should be viewed in the context of the extensive documentation provided by OSCAL.

                                            First, a Catalog is a collection of Controls, and a Profile imports controls and allows modification and additions to the controls, but it does not create new controls. A Profile has one or more Imports that refer either to an actual Catalog, or another Profile that itself is importing from a Catalog or Profile. The profiles can import controls selectively from each source and make additions or modifications to properties of the controls. The final collection of selected and modified controls represents the profile's resolved profile catalog.

                                            For clarity, here is a simple depicton of a catalog as a collection of controls:

                                            Here is a profile pulling controls from a catalog to make a resolved profile catalog:

                                            And here is a more complex situation where a single profile pulls controls from catalogs and profiles:

                                            From the diagram it's clear that the profile is performing many tasks under the covers. This is shown in an expanded view of a profile:

                                            It's important to note that each profile is importing a selection of controls from each source, then making its own suggested modifications to parameters and other content in those controls. They are suggested in the sense that downstream profiles may override those settings - with priority given to the later profiles in the pipeline. The changes made by upstream profiles may be accepted, or overridden by better choices for a given need. This way the catalogs themselves can remain relatively static, and individual use cases can effectively create a custom catalog based on the original controls plus modifications by other static profiles, and/or the user's custom profile. The authoring tools here provide ways to make those modifications, both to the catalog controls and to the profiles, and to enter the implementation responses that are needed in a System Security Plan.

                                            The tools are designed to be used in a continuous generate-edit-assemble cycle, with previous edits retained in each cycle. Each new edit phase can add or modify the current content, allowing a new generate of an OSCAL json document capturing those edits.

                                            NOTE: We use json format for specifying OSCAL files in this tutorial, but it is equally applicable to yaml format also.

                                            "},{"location":"tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/#the-author-commands-for-markdown-generation-and-assembly-to-json","title":"The author commands for markdown generation and assembly (to JSON)","text":"trestle author catalog-generate and trestle author catalog-assemble

                                            catalog-generate takes an existing json catalog and writes it out as markdown files for each control in a user-specified directory. That directory will contain subdirectories for each group in the catalog, and those directories may contain subdirectories for groups within groups. But controls containing controls are always split out into a series of controls in the same directory - and each control markdown file corresponds to a single control.

                                            We now look at the contents of a typical control markdown file.

                                            A Control may contain many parts, but only one of them is a Statement, which describes the function of the control. The statement itself is broken down into separate items, each of which may contain parameter id's in \"moustache\" ({{}}) brackets. Below is an example of a control as generated in markdown form by the catalog-generate command.

                                            Control example
                                            ---\nx-trestle-set-params:\n  ac-1_prm_1:\n    values:\n      - new value\n  ac-1_prm_2:\n    values:\n  ac-1_prm_3:\n    values:\n      - added param 3 value\n  ac-1_prm_4:\n    values:\n  ac-1_prm_5:\n    values:\n  ac-1_prm_6:\n    values:\n  ac-1_prm_7:\n    values:\nx-trestle-global:\n  sort-id: ac-01\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\n- \\[a.\\] Develop, document, and disseminate to {{ insert: param, ac-1_prm_1 }}:\n\n  - \\[1.\\]  {{ insert: param, ac-1_prm_2 }} access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an {{ insert: param, ac-1_prm_3 }} to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy {{ insert: param, ac-1_prm_4 }} and following {{ insert: param, ac-1_prm_5 }}; and\n  - \\[2.\\] Procedures {{ insert: param, ac-1_prm_6 }} and following {{ insert: param, ac-1_prm_7 }}.\n- \\[d\\] My added item\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. \n

                                            The control markdown files rely on brackets around key items that are important in defining the control's properties and structure. \\[Access Control\\] at the top indicates the title of the group containing the control. The name of the control is already known from the name of the markdown file (ac-1.md) and the name of the group is already known from the name of the directory containing the group's controls (ac) - but the group title must be indicated in the control in a special manner, hence the brackets. The text following the group title is the title of the control itself. All controls in a group should have the same group title or a warning will be indicated in certain trestle operations.

                                            In addition, each part label corresponds to the label used in the OSCAL structure for the control statement, and so must be maintained in a special manner - hence the need for brackets on \\[(a)\\].

                                            The items in moustaches ({{}}) correspond to the original prose from the control description. The moustaches represent places to substitue parameter values, but no substitutions are ever made until the final SSP generation. The authoring process provides multiple ways to set and change the final parameter values, as described below.

                                            catalog-generate is run with the command trestle author catalog-generate --name catalog_name --output markdown_dir, where catalog_name is the name of a catalog already loaded into the trestle workspace, and markdown_dir is the directory into which the markdown files for the controls will be written. A separate directory is created for each group in the catalog.

                                            A user then may edit the control statement for the control and add or change the contents. In this case an added item, My added item is shown as item d. You can then assemble the edited controls into a new catalog with the command trestle author catalog-assemble --markdown markdown_dir --output new_catalog. This will load the updated control statements for each control into a new json or yaml catalog named new_catalog.

                                            As with profile and ssp generation described below, a yaml header may be provided with the --yaml option that is inserted into the top of each control file. If a control file already exists, as is expected in a continuous cycle of generate-edit-assemble, then the provided header will be merged with the existing header in each control. If a given item in the header is already present in the control, by default the values in the markdown header will be given priority, though this can be overridden by the --overwrite-header-values option, which will give priority to any values coming from the provided yaml header. In all cases, values in the yaml header not already present in the markdown header will be inserted.

                                            In the control markdown example above, the header contains some arbitrary values along with a special x-trestle-set-params section containing parameters for some of the parameters in the control. Any parameters for the control in the catalog will appear in the markdown header automatically during catalog-generate. These values may be changed and values for other parameters may be inserted into the markdown header for later use during catalog-assemble.

                                            Parameters in the header are shown with a subset of their full OSCAL attributes in order to convey any values they may have along with descriptive text. This amounts to the parameter id, its label if present, any values if present, and any select if present. When a select is present the list of choices is provided along with the how-many option. Note that values is a list in OSCAL, but in many cases it is a list of only one item. As a result, for convenience the values: dictionary may either have one string value (on the same line with values:) or as an indented - list of multiple values underneath values:. Multiple examples are evident in the sample above, including ac-1_prm_3, which only has a label and no values.

                                            Another important item in the header is the sort-id for the control. This specifies how the controls and their parameters are ordered in any aggregated list operation. If it is not specified for a control, the control's id is used for sorting.

                                            As with the other -generate tools, the --force-overwrite option will cause the destination markdown directory to be erased prior to generating the new markdown, so that any prior edits to the markdown will be erased.

                                            catalog-assemble is run with the command catalog-assemble --markdown my_md --output my_new_catalog. This will read the markdown for each control and create a new catalog based on any edits to the markdown. Note that you may optionally provide a --name option specifying an original json catalog into which the updated controls are inserted, and the resulting catalog can either replace the original one or output to a different json file. New controls may be added but existing controls may not be removed and new groups cannot be added when you are updating an existing catalog. The main benefit of updating an existing catalog is that the original metadata and other contents of the catalog json file will be retained. Note that you cannot create new controls that contain controls, but if an original json catalog contains controls with child controls, you can edit and update all of them as individual markdown files. You have the option to specify a new --version for the catalog, and an option to regenerate the uuid's in the catalog. Finally, you have the option to use the parameters in the markdown header to update the values in the control. Any parameters and their values present will be added to the control, and any not present will be removed. The parameters themselves are still present but their values are removed.

                                            In a typical generate-edit-assemble cycle, the cycle would start with an original json file containing source content and metadata and use that to generate an initial markdown directory of controls. After editing the controls they would be assembled into into a new json file with a different name. But once that new file exists, it can be used as the source for the next generation and the original source document is no longer needed or referred to. For the catalog- editing cycle it would go as:

                                            trestle author catalog-generate --name orig_catalog --output md_catalog\n[user edits the markdown files]\ntrestle author catalog-assemble --name orig_catalog --markdown md_catalog --output assembled_catalog\n[user makes additional markdown edits]\ntrestle author catalog-assemble --markdown md_catalog --output assembled_catalog\n

                                            The key point here is that the first -assemble needs to use the original catalog for its metadata, backmatter and other items not captured in the markdown controls. But once the output catalog has been created, by default it will be used as the \"original\" or \"parent\" catalog into which changes will be incorporated, unless a different source catalog is specified via --name.

                                            Note that catalog-assemble can instantiate a catalog anew from a manually created directory of markdown controls in directories corresponding to groups, but the metadata in the assembled json catalog will contain many REPLACE_ME items that would need to be manually edited in the json file itself. The trestle split and merge tools may help in that case. Once the changes have been made they will be retained if a new catalog-assemble happens with that same output file as the target.

                                            Special Note about assemble: In order to avoid triggering actions when a new file is created that has no actual changes in it, catalog-assemble and the other -assemble tools below will check to see if the output file already exists, and if so it will be examined for changes relative to the newly assembled one. If there are no changes the file will not be written out. Note that the check happens before any possible --regeneration of uuid's, and after any possible --version change. This avoids the creation of a new file and new uuid's if there is no change to the version or other file contents relative to the existing output file, but if the specified --version is different from the one in the existing output file, or there is any other difference in the model, a new file will be written out.

                                            trestle author profile-generate and trestle author profile-assemble

                                            The background text above conveys how a profile pulls controls from catalogs and makes modifications to them, and the trestle profile tools let you change the way those modifications are made. In addition to selecting controls and setting parameters, a profile may add new parts to a control that provide additional guidance specific to a certain use case. profile-generate is run with the command, trestle author profile-generate --name profile_name --output markdown_dir. It will load the specified profile name from the trestle workspace (it must have been imported into the trestle workspace prior) and create its corresponding resolved profile catalog - but without applying any of its Adds of additonal guidance content or SetParameters. It will make all other modifications, but the Adds and SetParameters are kept separate, as shown below:

                                            Example of control markdown after `profile-generate`
                                            ---\nx-trestle-set-params:\n  # You may set values for parameters in the assembled Profile by adding\n  #\n  # profile-values:\n  #   - value 1\n  #   - value 2\n  #\n  # in the section under a parameter name\n  # The values list refers to the values in the catalog, and the profile-values represent values\n  # in SetParameters of the Profile.\n  #\n  ac-1_prm_1:\n    label: label from edit\n    profile-values:\n      - all personnel\n    values:\n      - Param_1_value_in_catalog\n    display-name: Pretty ac-1 prm 1\n  ac-1_prm_2:\n    profile-values:\n      - Organization-level\n      - System-level\n    values:\n    display-name: Pretty ac-1 prm 2\n  ac-1_prm_3:\n    profile-values:\n      - new value\n    values:\n  ac-1_prm_4:\n    profile-values:\n    values:\n  ac-1_prm_5:\n    profile-values:\n      - all meetings\n    values:\n  ac-1_prm_6:\n    profile-values:\n      - monthly\n    values:\n  ac-1_prm_7:\n    values:\nx-trestle-global:\n  profile:\n    title: Trestle test profile\n  sort-id: ac-01\nx-trestle-sections:\n  guidance: Guidance\n  implgdn: Implementation Guidance\n  expevid: Expected Evidence\n  my_guidance: My Guidance\n  a_guidance: A Guidance\n  b_guidance: B Guidance\n  NeededExtra: Needed Extra\n  a_subpart: A Subpart\n  a_subsubpart: A Subsubpart\n  b_subpart: B Subpart\n  a_by_id_subpart: a by_id subpart\nx-trestle-add-props:\n  # Add or modify control properties here\n  # Properties may be at the control or part level\n  # Add control level properties like this:\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #\n  # Add properties to a statement part like this, where \"b.\" is the label of the target statement part\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #     smt-part: b.\n  #\n  - name: prop_with_ns\n    value: prop with ns\n    ns: https://my_new_namespace\n  - name: prop_with_no_ns\n    value: prop with no ns\n    ns: https://my_added_namespace\n---\n\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\n- \\[a.\\] Develop, document, and disseminate to {{ insert: param, ac-1_prm_1 }}:\n\n  - \\[1.\\]  {{ insert: param, ac-1_prm_2 }} access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an {{ insert: param, ac-1_prm_3 }} to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy {{ insert: param, ac-1_prm_4 }} and following {{ insert: param, ac-1_prm_5 }}; and\n  - \\[2.\\] Procedures {{ insert: param, ac-1_prm_6 }} and following {{ insert: param, ac-1_prm_7 }}.\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. Policies and procedures contribute to security and privacy assurance. Therefore, it is important that security and privacy programs collaborate on the development of access control policy and procedures. Security and privacy program policies and procedures at the organization level are preferable, in general, and may obviate the need for mission- or system-specific policies and procedures. The policy can be included as part of the general security and privacy policy or be represented by multiple policies reflecting the complex nature of organizations. Procedures can be established for security and privacy programs, for mission or business processes, and for systems, if needed. Procedures describe how the policies or controls are implemented and can be directed at the individual or role that is the object of the procedure. Procedures can be documented in system security and privacy plans or in one or more separate documents. Events that may precipitate an update to access control policy and procedures include assessment or audit findings, security incidents or breaches, or changes in laws, executive orders, directives, regulations, policies, standards, and guidelines. Simply restating controls does not constitute an organizational policy or procedure.\n\n# Editable Content\n\n<!-- Make additions and edits below -->\n<!-- The above represents the contents of the control as received by the profile, prior to additions. -->\n<!-- If the profile makes additions to the control, they will appear below. -->\n<!-- The above markdown may not be edited but you may edit the content below, and/or introduce new additions to be made by the profile. -->\n<!-- If there is a yaml header at the top, parameter values may be edited. Use --set-parameters to incorporate the changes during assembly. -->\n<!-- The content here will then replace what is in the profile for this control, after running profile-assemble. -->\n<!-- The added parts in the profile for this control are below.  You may edit them and/or add new ones. -->\n<!-- Each addition must have a heading either of the form ## Control my_addition_name -->\n<!-- or ## Part a. (where the a. refers to one of the control statement labels.) -->\n<!-- \"## Control\" parts are new parts added after the statement part. -->\n<!-- \"## Part\" parts are new subparts added into the existing top-level statement part with that label. -->\n<!-- Subparts may be added with nested hash levels of the form ### My Subpart Name -->\n<!-- underneath the parent ## Control or ## Part being added -->\n<!-- See https://oscal-compass.github.io/compliance-trestle/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring for guidance. -->\n\n## Control Implementation Guidance\n\nDo it carefully.\n\n## Control Expected Evidence\n\nDetailed logs.\n\n## Control Needed Extra\n\nAdd prose here for required Section: Needed Extra\n\n## Control A Guidance\n\nControl level guidance\n\n### A Subpart\n\nA subpart prose\n\n#### A Subsubpart\n\nA subsubpart prose\n\n### B Subpart\n\nB subpart prose\n\n## Part a.\n\n### Subpart of top level Part a. of the control\n\nProse added as a sub-part to Part a. of the control\n

                                            In the above markdown example, the fixed, uneditable parts of the control are output first (after the header, which can be edited), followed by a separate section marked, Editable Content. And below the editable content are the individual Adds that the profile makes, with each one marked by a header of the form, ## Control guidance_name or ## Part statement_part_label followed by named subparts. You may edit the editable content and you may add new Control guidance headers and statement sub-parts with your own new content. (Please refer to Markdown Specifications for Editable Content section below to learn more on which headers are valid in Trestle.) Then the command, trestle author profile-assemble --name original_profile --markdown markdown_dir --output new_profile will create a new OSCAL profile based on the original profile (specified) and the editable content in each control.

                                            It's important to distinguish ## Control My New Guidance from ## Part a.. Parts added with ## Control will be new parts in the control added after the control statement, along with any subparts indicated by lower hash levels in that section. In contrast, parts added with e.g. ## Part c. will be added by-id to the top level part in the control statement with label c.. Thus \"My New Guidance\" is the title the user is assigning to a completely new part, while c. refers to a label corresponding the the desired control statement part.

                                            When new part names are created in the markdown file the title is captured along with its capitalization and spaces, but the corresponding part name will be converted to snake case by default. However, the user may indicate a specific mapping of the long title of the part to its actual part name by providing an entry in the sections provided during profile-assemble. For example, in the above, the Needed Extra part would be assigned the name needed_extra but if you had a section entry such as n_ex:Needed Extra the name n_ex would be assigned in the assembled json profile, so that if you used that same section entry trestle would know to replace the n_ex part with Needed Extra in any generated markdown.

                                            In a cyclic operation of profile generate-edit-assemble you would simply be re-writing from and to the same json profile, in which case the --name and --output are the same file. For this reason the default value for --name is the given output file name specified by --output and you can just use trestle author profile-assemble --markdown profile_md --output my_profile. This will assemble the markdown profile contents in directory profile_md into a json profile named my_profile but it will first use the existing my_profile json file as the parent profile and incorporate changes (due to user edits) in the markdown version of the profile. Unlike catalog-assemble there must always be a parent json profile to reference during assemble, but like catalog-assemble an explicit value for --name is only needed if the parent file is different from the assembled output file.

                                            It's important to note that these operations only apply to the Adds and SetParameters in the profile itself - and nothing upstream of the profile is affected. Nor is anything else in the original profile lost or altered. In the example above, the section, ## Control Implementation Guidance was added by editing the generated control - and after profile-assemble it ended up as new guidance in the assembled profile.

                                            As in the other commands, profile-generate allows specification of a yaml header with --yaml-header, support of the --overwrite-header-values flag and --force-overwrite. Also, during assembly with profile-assemble the --set-parameters flag will set parameters in the profile for the control based on the header in the control markdown file. But unlike with catalog-assemble, only those parameter values marked profile-values will be part of the assembled profile's SetParams when you assemble with the --set-parameters flag. For each parameter, the \"incoming\" values for the parameters prior to any changes made by the profile are listed as values: and any pending changes made by the profile are listed as profile-values:. If you don't use the --set-parameters flag then all the original SetParameters in the profile will be retained in the new, assembled profile. But if you do set that flag, then only the header parameters with profile-values: will be added as SetParameters. This lets you see all the incoming values for parameters along with any changes made by the current profile, and you can modify, add, or remove parameter settings as desired in the new profile.

                                            The x-trestle-add-props key of the yaml header allows addition of properties to the SetParameters of the profile, comprising name, value, and optionally a namespace ns value. The properties may be added at the control level, or attached to a top level statment part by adding a value, smt-part with value a., b. or any other label for one of the top level statement parts.

                                            For convenience, the x-trestle-global key of the yaml header contains the profile-title of the profile used to generate the markdown.

                                            Keep in mind that the header in the profile- tools corresponds to the SetParameters in the profile - and not simply the Parameters in the control. For convenience the current incoming values of the control parameters, as set by any upstream profiles, are shown as values - but anything else associated with a parameter, such as profile-values, label, choice will be added to the profile's SetParameters during profile-assemble (if you use the --set-parameters flag.) So entries should be set there only if you want the profile to enforce those entries as SetParameters.

                                            As with catalog-assemble described above, a new file is written out only if there are changes to the model relative to an existing output file, and during generate, --force-overwrite will first erase any existing markdown so that fresh markdown is created.

                                            Use of Sections in profile-generate and profile-assemble

                                            The addition of guidance sections in the profile tools requires special handling because the corresponding parts have both a name and a title, where the name is a short form used as an id in the json schema, while the title is the readable form intended for final presentation. An example is ImplGuidance vs. Implementation Guidance. The trestle authoring tools strive to make the markdown as readable as possible, therefore the headings for sections use the title - which means somehow there is a need for a mapping from the short name to the long title for each section. This mapping is provided in several ways: During profile-generate you may provide a --sections \"ImplGuidance:Implementation Guidance,ExpEvidence:Expected Evidence\" option that would provide title values for ImplGuidance and ExpEvidence. This dictionary mapping is then inserted into the yaml header of each control's markdown. You may also add this mapping directly to a yaml file that is passed in during profile-generate, which is preferable if the list of sections is long. The sections should be entered in the yaml header in a section titled, x-trestle-sections.

                                            There is also a --required-sections option during both profile-generate and profile-assemble. This option expects a list of sections as comma-separated short names, e.g. --required-sections \"ImplGuidance,ExpEvidence\". During profile-generate any required sections will have in the markdown a prompt created for guidance prose to be entered. And during profile-assemble if required sections are specified, those sections must have prose filled in or it will fail with error.

                                            Finally, profile-assemble also has an --allowed-sections option that restricts any added guidance to only those allowed sections - and if disallowed sections are present it will fail with error. If --allowed-sections is not specified then any sections found in the markdown will be added to the assembled profile.

                                            Note that these section options are all optional and there isn't a need to provide this form of restriction and enforcement. But in order to have such sections read properly and mapped to the intended part names, a mapping must be provided in one of the ways described above. And for certain workflows, if the allowed and required sections are specified by a command that is run as an action outside the user's control, it allows restriction of what changes can or must be made to a profile in terms of added guidance.

                                            (Note that the single quotes are required on Unix-like systems, but on Windows they are only needed if the contained string includes spaces, in which case double quotes should be used.)

                                            Markdown Specifications for Editable Content.

                                            For the ease of editing markdown in Github, Trestle's markdown parser follows Github Flavoured Markdown (GFM) specifications and therefore only certain Control headers will be parsed and added to the control.

                                            A valid control header in Trestle is the header that is correctly displayed as such when reading or previewing the edited markdown on Github website.

                                            In GFM, headers are considered to be any line of text that has any number of # symbols at the beginning. For example those are all valid headers and will be treated as such by Github:

                                            # Valid header\n## Valid header \n##### Valid header\n# Valid <ins> header </ins> \n# Valid header <!-- some comment here -->\n

                                            The headers above are valid Control headers and will be added to the control. However, there are multiple exceptions where the header will not be displayed. The header will not be displayed correctly if it is:

                                            1. Written in the HTML comments or tags <ins> # not a header </ins> as well as multi-line comments:
                                              <!--\n# not a header\n-->\n
                                              or multi-line HTML blocks:
                                              <dl> # not a header\n# not a header\n  <dt># not a header</dt>\n</dl>\n
                                            2. Written in the single-line # not a header and multi-line code blocks:
                                              # not a header \n
                                            3. Written in the links [# not a header](url)
                                            4. Trestle will also not support headers inside the blockquotes > # not a header

                                            In all cases above Trestle markdown parser will skip such headers and it will be not added to the control.

                                            trestle author profile-resolve

                                            The trestle author profile-resolve command is different from the generate/assemble commands because it doesn't involve markdown and instead it takes an input profile and creates the corresponding resolved profile catalog in JSON format. In addition, it has several options for how parameters are represented in prose of the controls, and whether or not those values are substituted.

                                            As an example, the prose in the statement for control AC-1 is:

                                            Develops, documents, and disseminates to {{ insert: param, ac-1_prm_1 }}:

                                            The parameter ac-1_prm_1 has a label: organization-defined personnel or roles and it may or may not have a value assigned by the profile being resolved. Suppose it has been assigned the value, my prm 1 value. In that case we can either leave the prose as-is (with the parameter in \"moustache\" form) in the resolved catalog, or we can substitute the value, or we can substitute the descriptive label. trestle supports all these options, along with an optional prefix to specify whether a value has been assigned or not - typically using the name of the organization responsible.

                                            The --show-value -sv option will cause the value for the parameter to be substituted in the prose if it is available - otherwise the list of selection options if it has any, or simply the label prose if it has no options.

                                            The --value-assigned-prefix -vap option adds a prefix to the value if the value is being assigned by the profile, and the --value-not-assigned-prefix -vnap will assign a prefix to parameters that do not have values assigned, along with the descriptive parameter label.

                                            Finally, the --bracket-format -bf option specifies how the parameter representation will be wrapped in braces. The specification is done by placing characters around a single . symbol representing the parameter string, e.g. [.] will place square brackets around the parameter.

                                            Note that these options that specify how the parameter is represented all require --show-value to be True, otherwise the raw prose with the moustache is produced.

                                            As an example, if we use options

                                            trestle author profile-resolve -n my_profile -o my_resolved_catalog -sv -bf [.] -vap \"ACME Assignment:\" -vnap \"Assignment:\"

                                            the above prose would become:

                                            Develops, documents, and disseminates to [ACME Assignment: my prm 1 value]:

                                            (Note that you need appropriate use of quotation marks in the command for any strings that include spaces or special characters.)

                                            And if the parameter did not have a value assigned the result would be:

                                            Develops, documents, and disseminates to [Assignment: organization-defined personell or roles]:

                                            Finally, if the parameter already had a value specified in the catalog, the value would be shown by itself in braces:

                                            Develops, documents, and disseminates to [value in catalog]:

                                            Similar substitution happens when a parameter has choices that themselves reference a parameter, such as:

                                            \"id\": \"ac-4.4_prm_1\",\n\"select\": {\n  \"how-many\": \"one-or-more\",\n  \"choice\": [\n    \"decrypting the information\",\n    \"blocking the flow of the encrypted information\",\n    \"terminating communications sessions attempting to pass encrypted information\",\n    \" {{ insert: param, ac-4.4_prm_2 }} \"\n  ]\n

                                            If the statement prose for AC-4.4 is:

                                            The information system prevents encrypted information from bypassing content-checking mechanisms by {{ insert: param, ac-4.4_prm_1 }}.

                                            and if a value pulling the plug has been assigned to ac-4.4_prm_2, the prose will be:

                                            The information system prevents encrypted information from bypassing content-checking mechanisms by [Selection (one or more): decrypting the information, blocking the flow of the encrypted information, terminating the communications sessions attempting to pass encrypted information, [ACME Assignment: pulling the plug]].

                                            There is a separate option from --show-values that will instead show only the descriptive labels for the parameters - again with an optional prefix. The options are --show-labels -sl and --label-prefix -lp. Note that there is no need for \"assigned\" or \"not assigned\" because no values are being shown - just the labels.

                                            If we resolve the profile with options --show-labels --label-prefix \"Label:\" --bracket-format [.] the resulting prose from earlier would be:

                                            Develops, documents, and disseminates to [Label: organization-defined personnel or roles]:

                                            and any value present for the parameter would be ignored.

                                            Similar options apply to the jinja authoring commands.

                                            trestle author profile-inherit

                                            The trestle author profile-inherit command is different from the generate/assemble commands because it doesn't involve markdown and instead it takes an parent profile and ssp and creates child profile in JSON format.

                                            When utilizing a process with leveraged authorizations, use the command trestle author profile-inherit to create a profile with initial content using a parent profile and SSP with inheritable controls. The provided and responsibility statements for all by-component fields, as well as the implementation status, will be used to evaluate the leveraged SSP. To be filtered from the output profile (i.e. controls delta profile), all components must have exported provided statements, no exported responsibility statements, and an implementation status of implemented.

                                            The filter command is invoked as:

                                            trestle author profile-inherit --profile my_parent --ssp my_leveraged_ssp --output controls_delta_profile

                                            Both the parent profile and the SSP must be present in the trestle workspace. This command produces a new workspace profile that imports the parent profile and filters the inherited controls from the SSP using the exclude-controls and include-controls fields in the profile import.

                                            Example imports generated from profile-inherit
                                              \"imports\": [\n{\n\"href\": \"trestle://profiles/controls_delta/profile.json\",\n\"include-controls\": [\n{\n\"with-ids\": [\n\"ac-2\"\n]\n}\n],\n\"exclude-controls\": [\n{\n\"with-ids\": [\n\"ac-1\"\n]\n}\n]\n}\n]\n
                                            trestle author component-generate and component-assemble

                                            The trestle author component-generate command takes a JSON ComponentDefinition file and creates markdown for its controls in separate directories for each of the DefinedComponents in the file. This allows specifying the implementation response and status for each component separately in separate markdown files for a control. In addition, the markdown captures Rules in the control that specify descriptions and parameter values that apply to the expected responses.

                                            The command has few options compared to other author commands and only requires specifying --name and --output for the ComponentDefinition and output markdown directory, respectively.

                                            Here is an example of the generated markdown for the component OSCO in the ComponentDefinition file. Note that this file will be under the subdirectory OSCO/source_name of the specified output directory - and any other DefinedComponents will have corresponding subdirectories level with the OSCO one. Here source_name refers to the name of the profile or catalog in the ComponentDefinition that is the source for this control. The control markdown files are written into directories split by both component name and source name. If the source refers to a general uri and not a named profile or catalog in the trestle directory, then names such as source_001 and source_002 are assigned. The actual source title can be found in the yaml header of any of the control markdown files.

                                            Example of control markdown after component-generate
                                            ---\nx-trestle-comp-def-rules:\n  comp_aa:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in aa\n    - name: comp_rule_aa_1\n      description: comp rule aa 1\nx-trestle-rules-params:\n  comp_aa:\n    - name: shared_param_1\n      description: shared param 1 in aa\n      options: '[\"shared_param_1_aa_opt_1\", \"shared_param_1_aa_opt_2\"]'\n      rule-id: top_shared_rule_1\nx-trestle-comp-def-rules-param-vals:\n  # You may set new values for rule parameters by adding\n  #\n  # component-values:\n  #   - value 1\n  #   - value 2\n  #\n  # below a section of values:\n  # The values list refers to the values as set by the components, and the component-values are the new values\n  # to be placed in SetParameters of the component definition.\n  #\n  comp_aa:\n    - name: shared_param_1\n      values:\n        - shared_param_1_aa_opt_1\nx-trestle-param-values:\n  ac-1_prm_1:\n    - prof_aa val 1\n  ac-1_prm_2:\n  ac-1_prm_3:\n  ac-1_prm_4:\n  ac-1_prm_5:\n  ac-1_prm_6:\n  ac-1_prm_7:\nx-trestle-global:\n  profile:\n    title: comp prof aa\n    href: trestle://profiles/comp_prof_aa/profile.json\n  sort-id: ac-01\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\nThe organization:\n\n- \\[a.\\] Develop, document, and disseminate to prof_aa val 1:\n\n  - \\[1.\\] Organization-level; Mission/business process-level; System-level access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an organization-defined official to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy organization-defined frequency and following organization-defined events; and\n  - \\[2.\\] Procedures organization-defined frequency and following organization-defined events.\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. Policies and procedures contribute to security and privacy assurance. Therefore, it is important that security and privacy programs collaborate on the development of access control policy and procedures. Security and privacy program policies and procedures at the organization level are preferable, in general, and may obviate the need for mission- or system-specific policies and procedures. The policy can be included as part of the general security and privacy policy or be represented by multiple policies reflecting the complex nature of organizations. Procedures can be established for security and privacy programs, for mission or business processes, and for systems, if needed. Procedures describe how the policies or controls are implemented and can be directed at the individual or role that is the object of the procedure. Procedures can be documented in system security and privacy plans or in one or more separate documents. Events that may precipitate an update to access control policy and procedures include assessment or audit findings, security incidents or breaches, or changes in laws, executive orders, directives, regulations, policies, standards, and guidelines. Simply restating controls does not constitute an organizational policy or procedure.\n\n______________________________________________________________________\n\n## What is the solution and how is it implemented?\n\n<!-- For implementation status enter one of: implemented, partial, planned, alternative, not-applicable -->\n\n<!-- Note that the list of rules under ### Rules: is read-only and changes will not be captured after assembly to JSON -->\n\nimp req prose for ac-1 from comp aa\n\n### Rules:\n\n- top_shared_rule_1\n\n### Implementation Status: implemented\n\n______________________________________________________________________\n\n## Implementation for part a.\n\nstatement prose for part a. from comp aa\n\n### Rules:\n\n- comp_rule_aa_1\n\n### Implementation Status: partial\n\n______________________________________________________________________\n

                                            There is no direct way to specify rules in the ComponentDefinition, so they are specified via properties as shown here:

                                            Representation of rules in the props of a ComponentDefinition
                                            [\n{\n\"name\": \"Rule_Id\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp_rule_aa_1\",\n\"class\": \"Rule_Id\",\n\"remarks\": \"rule_2\"\n},\n{\n\"name\": \"Rule_Description\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp rule aa 1\",\n\"remarks\": \"rule_2\"\n},\n{\n\"name\": \"Rule_Id\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp_rule_aa_2\",\n\"class\": \"Rule_Id\",\n\"remarks\": \"rule_3\"\n},\n{\n\"name\": \"Rule_Description\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp rule aa 2\",\n\"class\": \"Rule_Description\",\n\"remarks\": \"rule_3\"\n},\n{\n\"name\": \"Parameter_Id\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"shared_param_1\",\n\"class\": \"Parameter_Id\",\n\"remarks\": \"rule_1\"\n},\n{\n\"name\": \"Parameter_Description\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"shared param 1 in aa\",\n\"class\": \"Parameter_Description\",\n\"remarks\": \"rule_1\"\n},\n{\n\"name\": \"Parameter_Value_Alternatives\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"[\\\"shared_param_1_aa_opt_1\\\", \\\"shared_param_1_aa_opt_2\\\"]\",\n\"class\": \"Parameter_Value_Alternatives\",\n\"remarks\": \"rule_1\"\n}\n],\n\"set-parameters\": [\n{\n\"param-id\": \"shared_param_1\",\n\"values\": [\n\"shared_param_1_aa_opt_1\"\n],\n\"remarks\": \"set shared param aa 1\"\n}\n]\n

                                            In this scheme the rules have a Rule_Id (e.g. comp_rule_aa_1 in this example) and an associated tag (rule_2) in the remarks section that binds the name to the description: Rule_Description=comp rule aa 1. In addition, rules may be associated with parameters specified here with Parameter_id=shared_param_1, Parameter_Description=shared param 1 in aa, and Parameter_Value_Alternatives=[\\\"shared_param_1_aa_opt_1\\\", \\\"shared_param_1_aa_opt_2\\\"]. Parameter_Value_Alternatives corresponds to possible Choices for the parameter value.

                                            Also shown in this JSON excerpt is a normal set-parameter used to set the value of a parameter associated with a rule id. Thus the setting of the parameter follows the normal OSCAL schema for setting a parameter value, while the specification of the parameter and its options is specified via linked properties.

                                            The markdown header lists all the rules that apply to this control, along with their descriptions, and for each implementation response, the rules that apply to it are shown. The association of an ImplementedRequirement with a rule is again done with properties as shown here:

                                            Linking of ImplementedRequirement to a rule
                                            {\n\"implemented-requirements\": [\n{\n\"uuid\": \"ca5ea4c5-ba51-4b1d-932a-5606891b7500\",\n\"control-id\": \"ac-1\",\n\"description\": \"imp req prose for ac-1 from comp aa\",\n\"props\": [\n{\n\"name\": \"Rule_Id\",\n\"value\": \"top_shared_rule_1\"\n},\n{\n\"name\": \"implementation-status\",\n\"value\": \"implemented\"\n}\n]\n}\n]\n}\n

                                            The values for rule parameters are specified using the normal SetParameter mechanism in the ControlImplementation, but it's important to note that there are two different types of SetParameter: Those that apply to the normal parameters of the control, and those that apply strictly to the rules.

                                            Note that markdown for a control is only created if there are rules associated with the control, and within the markdown the only parts written out that prompt for responses are parts that have rules assigned. Thus the output markdown directory may be highly pruned of both controls and groups of controls if only some controls have rules associated.

                                            In addition, the rules should be regarded as read-only from the editing perspective, and you cannot change the rules associated with a control or its parts. But you may edit the rule parameter values as described in the comments of the markdown file under x-trestle-comp-def-rules-param-vals. You may also edit the prose and implementation status associated with a statement part at the bottom of the markdown file.

                                            trestle author component-assemble

                                            The component-assemble command will assemble the markdown into a ComponentDefinition file containing all the DefinedComponents in the markdown, and as usual it can either overwrite the original JSON file or create a new one. Edits made to the prose, status and rule parameter values in the markdown and header will be captured in the assembled file, but the list of rules attached with each ImplementedRequirement is readonly and new rule associations cannot be made via markdown.

                                            trestle author ssp-generate and trestle author ssp-assemble

                                            The ssp-generate command creates markdown for an SSP (System Security Plan) from a profile, optional component definitions, and optional yaml header file. ssp-assemble (described below) can then assemble the markdown files into a single json SSP file. The profile contains a list of imports that are either a direct reference to a catalog, or an indirect reference via a profile. There may be multiple imports of either type, and referenced profiles may themselves import either catalogs or profiles. Each profile involved may specify the controls that should be imported, along with any modifications to those controls. This command internally creates a resolved profile catalog and generates a directory containing a set of markdown files, one for each control in the resolved catalog. Each markdown file has the optional yaml header embedded at the start of the file.

                                            The component definitions specify the components of the SSP, along with metadata associated with rules and status for the implemented requirements. The rules, rule parameters, and status values are encoded by properties within the components as described above for component-generate.

                                            Example usage for creation of the markdown:

                                            trestle author ssp-generate --profile my_prof --compdefs \"compdef_a,compdef_b\" --yaml /my_yaml_dir/header.yaml --output my_ssp

                                            In this example the profile and component definitions have previously been imported into the trestle directory. The profile itself must be in the trestle directory, but the imported catalogs and profiles may be URI's with href's as described below.

                                            The generated markdown output will be placed in the trestle subdirectory my_ssp with a subdirectory for each control group.

                                            If the imported catalogs or profiles are not at the URI pointed to by the Import href of the profile then the href should be changed using the trestle href command.

                                            Similar to catalog-generate, the --yaml and --overwrite-header-values flag may be specified to let the input yaml header overwrite values already specified in the header of the control markdown file. Also, the --force-overwrite option can be used to overwrite markdowns with content from JSON.

                                            The resulting files look like this:

                                            Example of control markdown after ssp-generate
                                            ---\nx-trestle-comp-def-rules:\n  comp_aa:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in aa\n    - name: comp_rule_aa_1\n      description: comp rule aa 1\n  comp_ab:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in ab\n    - name: comp_rule_ab_1\n      description: comp rule ab 1\n  comp_ba:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in ba\n  comp_bb:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in bb\nx-trestle-rules-params:\n  comp_aa:\n    - name: shared_param_1\n      description: shared param 1 in aa\n      options: '[\"shared_param_1_aa_opt_1\", \"shared_param_1_aa_opt_2\"]'\n      rule-id: top_shared_rule_1\n  comp_ab:\n    - name: shared_param_1\n      description: shared param 1 in ab\n      options: '[\"shared_param_1_ab_opt_1\", \"shared_param_1_ab_opt_2\"]'\n      rule-id: top_shared_rule_1\n  comp_ba:\n    - name: shared_param_1\n      description: shared param 1 in ba\n      options: '[\"shared_param_1_ba_opt_1\", \"shared_param_1_ba_opt_2\"]'\n      rule-id: top_shared_rule_1\n  comp_bb:\n    - name: shared_param_1\n      description: shared param 1 in bb\n      options: '[\"shared_param_1_bb_opt_1\", \"shared_param_1_bb_opt_2\"]'\n      rule-id: top_shared_rule_1\nx-trestle-comp-def-rules-param-vals:\n  # You may set new values for rule parameters by adding\n  #\n  # ssp-values:\n  #   - value 1\n  #   - value 2\n  #\n  # below a section of values:\n  # The values list refers to the values as set by the components, and the ssp-values are the new values\n  # to be placed in SetParameters of the SSP.\n  #\n  comp_aa:\n    - name: shared_param_1\n      values:\n        - shared_param_1_aa_opt_1\n      ssp-values:\n        - shared_param_1_aa_opt_2\n  comp_ab:\n    - name: shared_param_1\n      values:\n        - shared_param_1_ab_opt_2\nx-trestle-set-params:\n  # You may set values for parameters in the assembled SSP by adding\n  #\n  # ssp-values:\n  #   - value 1\n  #   - value 2\n  #\n  # below a section of values:\n  # The values list refers to the values in the resolved profile catalog, and the ssp-values represent new values\n  # to be placed in SetParameters of the SSP.\n  #\n  ac-1_prm_1:\n    values:\n      - comp_prof val 1\n    display-name: AC-1 (a) (1)\n  ac-1_prm_2:\n    values:\n  ac-1_prm_3:\n    values:\n  ac-1_prm_4:\n    values:\n  ac-1_prm_5:\n    values:\n  ac-1_prm_6:\n    values:\n  ac-1_prm_7:\n    values:\nx-trestle-global:\n  profile:\n    title: comp prof aa\n    href: trestle://profiles/comp_prof/profile.json\n  sort-id: ac-01\nx-trestle-add-props:\n  # Add or modify control properties here\n  # Properties may be at the control or part level\n  # Add control level properties like this:\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #\n  # Add properties to a statement part like this, where \"b.\" is the label of the target statement part\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #     smt-part: b.\n  #\n  - name: prop_with_ns\n    value: prop with ns\n    ns: https://my_new_namespace\n  - name: prop_with_no_ns\n    value: prop with no ns\n    ns: https://my_added_namespace\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\nThe organization:\n\n- \\[a.\\] Develop, document, and disseminate to [comp_prof val 1]:\n\n  - \\[1.\\] [Organization-level; Mission/business process-level; System-level] access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an [organization-defined official] to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy [organization-defined frequency] and following [organization-defined events]; and\n  - \\[2.\\] Procedures [organization-defined frequency] and following [organization-defined events].\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. Policies and procedures contribute to security and privacy assurance. Therefore, it is important that security and privacy programs collaborate on the development of access control policy and procedures. Security and privacy program policies and procedures at the organization level are preferable, in general, and may obviate the need for mission- or system-specific policies and procedures. The policy can be included as part of the general security and privacy policy or be represented by multiple policies reflecting the complex nature of organizations. Procedures can be established for security and privacy programs, for mission or business processes, and for systems, if needed. Procedures describe how the policies or controls are implemented and can be directed at the individual or role that is the object of the procedure. Procedures can be documented in system security and privacy plans or in one or more separate documents. Events that may precipitate an update to access control policy and procedures include assessment or audit findings, security incidents or breaches, or changes in laws, executive orders, directives, regulations, policies, standards, and guidelines. Simply restating controls does not constitute an organizational policy or procedure.\n\n______________________________________________________________________\n\n## What is the solution and how is it implemented?\n\n<!-- For implementation status enter one of: implemented, partial, planned, alternative, not-applicable -->\n\n<!-- Note that the list of rules under ### Rules: is read-only and changes will not be captured after assembly to JSON -->\n\n### This System\n\n<!-- Add implementation prose for the main This System component for control: ac-1 -->\n\n#### Implementation Status: planned\n\n### comp_aa\n\nimp req prose for ac-1 from comp aa\n\n#### Rules:\n\n- top_shared_rule_1\n\n#### Implementation Status: implemented\n\n### comp_ab\n\n<!-- Add control implementation description here for control: ac-1 -->\n\n#### Rules:\n\n- top_shared_rule_1\n\n#### Implementation Status: implemented\n\n______________________________________________________________________\n\n## Implementation for part a.\n\n### comp_aa\n\nstatement prose for part a. from comp aa\n\n#### Rules:\n\n- comp_rule_aa_1\n\n#### Implementation Status: partial\n\n### comp_ab\n\n<!-- Add control implementation description here for item a. -->\n\n#### Rules:\n\n- comp_rule_ab_1\n\n#### Implementation Status: partial\n\n______________________________________________________________________\n

                                            \\ Each label in the ssp is wrapped in \\[ \\] to indicate it comes directly from the label in the control and is not generated by the markdown viewer. Keep in mind that the actual label is the same but with the \\[ \\] removed.

                                            Note that for each statement in the control description there is a corresponding response section in which to provide a detailed response for later inclusion in the final ssp as the control implementation.

                                            Also note that the optional final sections are provided, and labeled using the title for the corresponding section.

                                            In addition, this is the only control markdown where the moustache ({{}}) items have been replaced by the corresponding parameter values in the final resolved profile catalog, surrounded by brackets, so that the prose corresponds to the final intended control and its implementation.

                                            The markdown can have guidance per-component in the control, as shown by the line, ### ACME Component. Any prose directly under a ## implementation section will apply to the overall system component, but sections in a sub-header of the form ### will only apply to that particular component.

                                            After generating the markdown for the resolved profile catalog you may then edit the files and provide text in the sections with Add control implementation... in them. But do not remove the horizontal rule lines or modify/remove the lines with ### in them, corresponding to system components.

                                            If you edit the control markdown files you may run ssp-generate again and your edits will not be overwritten. When writing out the markdown for a control, any existing markdown for that control will be read and the response text for each part will be re-inserted into the new markdown file. If the new markdown has added parts the original responses will be placed correctly in the new file, but if any part is removed from the source control json file then any corresponding prose will be lost after the next ssp-generate.

                                            The x-trestle-add-props key of the yaml header allows the addition of properties to the implemented requirements under the SSP control implementation, comprising name, value, and optionally a namespace ns value. Similarly to the x-trestle-add-props in profile authoring, the properties may be added at the control level, or attached to a top level statement part by adding a value, smt-part with value a., b. or any other label for one of the top level statement parts.

                                            trestle author ssp-assemble

                                            After manually edting the markdown and providing the responses for the control implementation requirements, the markdown can be assembled into a single json SSP file with:

                                            trestle author ssp-assemble --markdown my_ssp --compdefs my_compdef_a,my_compdef_b --output my_json_ssp

                                            This will assemble the markdown files in the my_ssp directory and create a json SSP with name my_json_ssp in the system-security-plans directory.

                                            As indicated for ssp-generate, please do not alter any of the horizontal rule lines or lines indicating the part or control id, e.g. ### ACME Component. You may run ssp-generate and ssp-assemble repeatedly for the same markdown directory, allowing a continuous editing and updating cycle.

                                            As with all the assemble tools, you may optionally specify a --name for a corresponding json file into which the updates will be inserted, thereby preserving metadata and other aspects of the model. The result can overwrite the provided model or get directed to a new model. And the version may be updated and the uuid's regenerated. As with the other -assemble tools, if an output file already exists, a new one will only be written if there are changes to the model relative to the existing file. See catalog-assemble for more details.

                                            If you do not specify component-defintions during assembly, the markdown should not refer to any components other than This System. Thus you may first generate markdown with ssp-generate and no component-definitions specified - and then you may assemble that ssp with ssp-assemble and no component-definitions specified - but only if there are no components other than This System referenced in the markdown. You may add new component implementation details to the markdown later, but any new components must be defined in a component-defintion file, and that file must be specified when ssp-assemble is run.

                                            ssp inheritance view

                                            The inheritance view is generated by setting the --leveraged-ssp flag with trestle author ssp-generate. It contains information relating to exported information such as inherited capabilities and customer responsibilities that can be used to populate the inheritance information in the assembled SSP. When used, a directory named \"inheritance\" is created within the markdown directory. This directory serves as a designated space for mapping inherited capabilities and responsibilities onto components in the assemble SSP and authoring satisfied statements for responsibilities.

                                            Example usage for creation of the markdown:

                                            trestle author ssp-generate --profile my_prof --compdefs \"compdef_a,compdef_b\" --yaml /my_yaml_dir/header.yaml --leveraged-ssp my_provider_ssp --output my_ssp

                                            In this example the leveraged ssp has previously been imported into the trestle directory, but it can be fetched from remote location.

                                            The generated markdown output with the inheritance view will be placed in the trestle subdirectory my_ssp/inheritance with a subdirectory for each component in the leveraged ssp with directories separated by control and statement id below.

                                            An example of this directory structure is below.

                                            .\n\u251c\u2500\u2500 Application\n\u2502   \u251c\u2500\u2500 ac-1_stmt.a\n\u2502   \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001001002006.md\n\u2502   \u251c\u2500\u2500 ac-2.1\n\u2502   \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001001002004.md\n\u2502   \u2514\u2500\u2500 ac-2_stmt.a\n\u2502       \u2514\u2500\u2500 11111111-0000-4000-9009-002001002001_11111111-0000-4000-9009-002001002002.md\n\u2514\u2500\u2500 This System\n    \u251c\u2500\u2500 ac-1_stmt.a\n    \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001002002001.md\n    \u251c\u2500\u2500 ac-2.1\n    \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001001002001.md\n    \u2514\u2500\u2500 ac-2_stmt.a\n        \u2514\u2500\u2500 11111111-0000-4000-9009-002001001001.md\n

                                            The leveraged components are used as the top level directory to allow any non-leveraged components to be easily skipped or removed. Each markdown file is named in accordance with the uuid of the exported statement to ensure statement description updates can be applied.

                                            There are three types of markdown files that can be generated from this process.

                                            The examples below demonstrate these types:

                                            Example of inheritance provided only markdown after ssp-generate
                                            ---\nx-trestle-statement:\n  # Add or modify leveraged SSP Statements here.\n  provided-uuid: 11111111-0000-4000-9009-001002002001\nx-trestle-leveraging-comp:\n  # Leveraged statements can be optionally associated with components in this system.\n  # Associate leveraged statements to Components of this system here:\n  - name: REPLACE_ME\n---\n\n# Provided Statement Description\n\nCustomer_appropriate description of what may be inherited.\n
                                            Example of inheritance customer responsibility only markdown after ssp-generate
                                            ---\nx-trestle-statement:\n  # Add or modify leveraged SSP Statements here.\n  responsibility-uuid: 11111111-0000-4000-9009-002001001001\nx-trestle-leveraging-comp:\n  # Leveraged statements can be optionally associated with components in this system.\n  # Associate leveraged statements to Components of this system here:\n  - name: REPLACE_ME\n---\n\n# Responsibility Statement Description\n\nLeveraging system's responsibilities with respect to inheriting this capability.\n\n# Satisfied Statement Description\n\n<!-- Use this section to explain how the inherited responsibility is being satisfied. -->\n
                                            Example of inheritance shared responsibility markdown after ssp-generate
                                            ---\nx-trestle-statement:\n  # Add or modify leveraged SSP Statements here.\n  provided-uuid: 11111111-0000-4000-9009-002001002001\n  responsibility-uuid: 11111111-0000-4000-9009-002001002002\nx-trestle-leveraging-comp:\n  # Leveraged statements can be optionally associated with components in this system.\n  # Associate leveraged statements to Components of this system here:\n  - name: REPLACE_ME\n---\n\n# Provided Statement Description\n\nConsumer-appropriate description of what may be inherited.\n\n# Responsibility Statement Description\n\nLeveraging system's responsibilities with respect to inheriting this capability.\n\n# Satisfied Statement Description\n\n<!-- Use this section to explain how the inherited responsibility is being satisfied. -->\n

                                            Some additional information and tips about this markdown are below:

                                            • Do not change the statement UUIDs in the YAML header. This is used in the assembled JSON to link the statements in the leveraged SSP to the components in the leveraging SSP.
                                            • When mapping components in the YAML header, use the component title. If you do not wish to map a component to a particular inherited capability or responsibility, just leave the file as is. Files without mapped components or that contain the default \"REPLACE ME\" entry will be skipped.
                                            • If the file exists, just the editable information will be preserved when regenerating existing inheritance view markdown. This includes the information under Satisfied Statement Description and the mapped components in the YAML header.

                                            After manually editing the inheritance view markdown, the trestle author ssp-assemble command can be run without modifications for the inheritance view use case. During assemble, the inheritance directory is detected and the information will be assembled into the SSP. The by-component assemblies will be updated or added under existing implemented requirement or statement sections with the information from the markdown.

                                            trestle author ssp-filter

                                            Once you have an SSP in the trestle directory you can filter its contents with a profile, list of components, list of implementation statuses, or list control origination values by using the command trestle author ssp-filter. The SSP is assumed to contain a superset of the controls needed by the profile if a profile is specified, and the filter operation will generate a new SSP with only those controls needed by the profile. If a list of component names is provided, only the specified components will appear in the system implementation of the ssp. If a list of implementation statuses is provided, controls with implementations including those statuses will appear in the control implementation of the ssp. Similarly, if a list of control origination values is provided, implemented requirements with a control origination property value included in the provided values will appear in the control implementation of the ssp.

                                            The filter command is invoked as:

                                            trestle author ssp-filter --name my_ssp --profile my_profile --components comp_a:comp_b --implementation-status \"planned,partial\" --control-origination \"customer-configured\" --output my_culled_ssp

                                            The SSP must be present in the trestle workspace and, if filtering by profile, that profile must also be in the trestle workspace. This command will generate a new SSP in the workspace. If the profile makes reference to a control not in the SSP then the routine will fail with an error message. Similarly, if one of the components is not present in the ssp the routine will also fail. The implementation statuses must be one of the allowed values as defined in the OSCAL SSP JSON format reference. Those include the following: implemented, partial, planned, alternative, and not-applicable. If an invalid value is provided, an error is returned. The control origination values also must be one of the allowed values as defined in the OSCAL SSP JSON format reference. Those include the following: system-specific, inherited, customer-configured, customer-provided, and organization. If an invalid value is provided, an error is returned.

                                            Summary of options used by the catalog, profile, component and ssp authoring tools.

                                            The provided options for the generation and assembly of documents in the ssp workflow is rich and powerful, but can also be confusing. To help see how they all relate please consult the following diagram showing the required and optional command line arguments for each command. The checkboxes indicate required and the open circles represent optional.

                                            The options shown are fairly consistent across the -generate and -assemble functions, but some clarification may be needed. For catalog-assemble and profile-assemble you have the option to use an existing json file as a parent model into which new content is inserted - in memory - and the final model may either be written back into that same json file, or a different one - based on --output. If you just want to keep editing and modifying the same original json file you can specify --name and --output to be the same, original json file. But you could also direct it to a new json file while still using an original file as the \"parent.\" A key benefit of referencing an original json file is the resuse of metadata and backmatter - along with everything else separate from the controls.

                                            ssp-generate is special because it starts with a profile rather than an ssp, whereas catalog-generate and profile-generate both start with a parent model of the same type. Nonetheless, you still have an option during ssp-assemble to use a given json file as the template into which new content is inserted, and once again you may overwrite that original json file or direct it to a new one using --output.

                                            "},{"location":"tutorials/task.csv-to-oscal-cd/transformation/","title":"Tutorial: Setup for and use of standard format csv-file to OSCAL Component Definition json-file transformer","text":"

                                            Here are step by step instructions for setup and transformation of trestle standard format csv-file into OSCAL Component Definition json-file using the compliance-trestle tool.

                                            "},{"location":"tutorials/task.csv-to-oscal-cd/transformation/#objective","title":"Objective","text":"

                                            How to transform trestle standard format csv-file into a component-definition.json file.

                                            There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from .csv to component-definition.json.

                                            Table: expected .csv content

                                            The below table represents the expectations of trestle task csv-to-oscal-cd for the contents of the input csv-file for synthesis of the output OSCAL Component Definition json-file.

                                            Column Name is the name of the expected column in the input csv-file. Any additional columns not identified here, for example foobar, are also extracted and placed into the output json-file as component.control-implementation.prop[\"foobar\"].

                                            Component Definition Locale is the path within the output json-file into witch the value is stashed.

                                            Column Name Value Type Specification Value Description Component Definition Locale Example Value Rule_Id String required A textual label that uniquely identifies a policy (desired state) that can be used to reference it elsewhere in this or other documents. component.control-implementation.prop[\"Rule_Id\"] password_policy_min_length_characters Rule_Description String required A description of the policy (desired state) including information about its purpose and scope. component.control-implementation.prop[\"Rule_Description\"] Ensure password policy requires minimum length of 12 characters Profile_Reference_URL String required A URL reference to the source catalog or profile for which this component is implementing controls for. A profile designates a selection and configuration of controls from one or more catalogs component.control-implementation.source https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_HIGH-baseline_profile.json Profile_Description String required A description of the profile. component.control-implementation.description NIST Special Publication 800-53 Revision 5 HIGH IMPACT BASELINE Component_Type String required A category describing the purpose of the component. component.type Validation Control_Mappings String List (blank separated) required A list of textual labels that uniquely identify the controls or statements that the component implements. component.control-implementation.implemented-requirement.statement.statement-id*and*component.control-implementation.implemented-requirement.control-id ia-5.1_smt.a ia-5.1 Resource String required A human readable name for the component. component.title Compliance Center Parameter_Id String optional A textual label that uniquely identifies the parameter associated with that policy (desired state) or controls implemented by the policy (desired state). A description of the parameter including the purpose and use of the parameter. component.control-implementation.prop[\"Parameter_Id\"]*and*component.control-implementation.set-parameter.param-id minimum_password_length Parameter_Description String optional A description of the parameter including the purpose and use of the parameter. component.control-implementation.prop[\"Parameter_Description\"] Minimum Password Parameter_Default_Value String optional A value recommended in this profile for the parameter of the control or policy (desired state). component.control-implementation.set-parameter.values 12 Parameter_Value_Alternatives String List (blank separated) optional ONLY for the policy (desired state) parameters: A value or set of values the parameter can take. component.control-implementation.prop[\"Parameter_Value_Alternatives\"] 12 8 Check_Id String optional A textual label that uniquely identifies a check of the policy (desired state) that can be used to reference it elsewhere in this or other documents. component.control-implementation.prop[\"Check_Id\"] check_password_policy_min_length_characters Check_Description String optional A description of the check of the policy (desired state) including the method (interview or examine or test) and procedure details. component.control-implementation.prop[\"Check_Description\"] Check whether password policy requires minimum length of 12 characters Fetcher String optional A textual label that uniquely identifies a collector of the actual state (evidence) associated with the policy (desired state) that can be used to reference it elsewhere in this or other documents. component.control-implementation.prop[\"Fetcher\"] fetch_password_policy_min_length_characters Fetcher_Description String optional A description of the collector of the actual state (evidence) associated with the policy (desired state) including the method (interview or examine or API) and questionaire component.control-implementation.prop[\"Fetcher_Description\"] Fetch whether password policy requires minimum length of 12 characters Resource_Instance_Type String optional A textual label that uniquely identifies a resource (component) type from the resource instance id. This text is part of all instance ids of a particular resource at runtime. For example the text 'db2' is part of all instance ids of resource DB2. component.control-implementation.prop[\"Resource_Instance_Type\"] DB2"},{"location":"tutorials/task.csv-to-oscal-cd/transformation/#step-1-install-trestle-in-a-python-virtual-environment","title":"Step 1: Install trestle in a Python virtual environment","text":"

                                            Follow the instructions here to install trestle in a virtual environment.

                                            "},{"location":"tutorials/task.csv-to-oscal-cd/transformation/#step-2-transform-profile-data-cis-benchmarks","title":"Step 2: Transform profile data (CIS benchmarks)","text":"

                                            Linux, Mac

                                            Windows

                                            Make these changes:

                                            • use backslashes `\\` for file paths
                                            • use `md` instead of mkdir -p
                                            • put the url in double quotes for `curl`
                                            • use `more` instead of cat
                                            • Navigate to trestle workspace.
                                            (venv.trestle)$ cd trestle.workspace\n
                                            • View configuration information.
                                            (venv.trestle)$ trestle task csv-to-oscal-cd -i\ntrestle.core.commands.task:101 WARNING: Config file was not configured with the appropriate section for the task: \"[task.csv-to-oscal-cd]\"\nHelp information for csv-to-oscal-cd task.\n\nPurpose: From csv produce OSCAL component_definition file.\n\n\nConfiguration flags sit under [task.csv-to-oscal-cd]:\n  title             = (required) the component definition title.\n  version           = (required) the component definition version.\n  csv-file          = (required) the path of the csv file.\n  required columns:   Rule_Id\n                      Rule_Description\n                      Profile_Reference_URL\n                      Profile_Description\n                      Component_Type\n                      Control_Mappings\n                      Resource\n  optional columns:   Parameter_Id\n                      Parameter_Description\n                      Parameter_Default_Value\n                      Parameter_Value_Alternatives\n                      Check_Id\n                      Check_Description\n                      Fetcher\n                      Fetcher_Description\n                      Resource_Instance_Type\n  output-dir        = (required) the path of the output directory for synthesized OSCAL .json files.\n  namespace         = (optional) the namespace for properties, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/cd\n  user-namespace    = (optional) the user-namespace for properties, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/cd/user-defined\n  class.column-name = (optional) the class to associate with the specified column name, e.g. class.Rule_Id = scc_class\n  output-overwrite  = (optional) true [default] or false; replace existing output when true.\n
                                            • Create data folder.
                                            (venv.trestle)$ mkdir -p adjunct-data\n
                                            • Fetch sample csv-file.
                                            (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.csv-to-oscal-cd/ocp4-sample-input.csv' > adjunct-data/ocp4-sample-input.csv\n
                                            • Fetch trestle task file.
                                            (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.csv-to-oscal-cd/demo-csv-to-oscal-cd.config' > adjunct-data/task-files/demo-csv-to-oscal-cd.config\n
                                            demo-csv-to-oscal-cd.config
                                            [task.csv-to-oscal-cd]\n\ncsv-file = adjunct-data/ocp4-sample-input.csv\noutput-dir = component-definitions/ocp4-sample\ntitle = ocp4-sample\nversion = 1.0\n
                                            • Perform and validate the transform.
                                            (venv.trestle)$ trestle task csv-to-oscal-cd -c demo-csv-to-oscal-cd.config \ninput: adjunct-data/ocp4-sample-input.csv\noutput: component-definitions/ocp4-sample/component-definition.json\nTask: csv-to-oscal-cd executed successfully.\n
                                            • View the generated OSCAL.
                                            (venv.trestle)$ component-definitions/ocp4-sample/component-definition.json\n
                                            component-definition.json
                                            {\n  \"component-definition\": {\n    \"uuid\": \"83cc8984-b00a-4799-885c-60b689efebd0\",\n    \"metadata\": {\n      \"title\": \"ocp4-sample\",\n      \"last-modified\": \"2022-11-18T17:06:49+00:00\",\n      \"version\": \"1.0\",\n      \"oscal-version\": \"1.0.2\"\n    },\n    \"components\": [\n      {\n        \"uuid\": \"c0080494-186a-421d-9afd-f51e0359cbd8\",\n        \"type\": \"Service\",\n        \"title\": \"OSCO\",\n        \"description\": \"\",\n        \"control-implementations\": [\n          {\n            \"uuid\": \"43a69f86-a3ad-40fa-ada6-2f988b951728\",\n            \"source\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile\",\n            \"description\": \"ocp4\",\n            \"props\": [\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_anonymous_auth\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --anonymous-auth argument is set to false\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_anonymous_auth\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --anonymous-auth argument is set to false\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_basic_auth\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --basic-auth-file argument is not set\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_basic_auth\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --basic-auth-file argument is not set\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_token_auth\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --token-auth-file parameter is not set\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_token_auth\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --token-auth-file parameter is not set\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_https_for_kubelet_conn\",\n                \"remarks\": \"rule_set_3\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --kubelet-https argument is set to true\",\n                \"remarks\": \"rule_set_3\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_https_for_kubelet_conn\",\n                \"remarks\": \"rule_set_3\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --kubelet-https argument is set to true\",\n                \"remarks\": \"rule_set_3\"\n              }\n            ],\n            \"implemented-requirements\": [\n              {\n                \"uuid\": \"c2893d38-1be4-4b0e-a090-96e846e15a3b\",\n                \"control-id\": \"CIS-1.2.1\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_anonymous_auth\"\n                  }\n                ]\n              },\n              {\n                \"uuid\": \"3c2f7129-9724-47c0-aadb-3b3c9c44995c\",\n                \"control-id\": \"CIS-1.2.2\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_basic_auth\"\n                  }\n                ]\n              },\n              {\n                \"uuid\": \"a4e2862f-7a1b-4182-b827-f5e797f589db\",\n                \"control-id\": \"CIS-1.2.3\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_token_auth\"\n                  }\n                ]\n              },\n              {\n                \"uuid\": \"daec13ab-829e-4dd6-a9d6-9ad18391681e\",\n                \"control-id\": \"CIS-1.2.4\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_https_for_kubelet_conn\"\n                  }\n                ]\n              }\n            ]\n          }\n        ]\n      }\n    ]\n  }\n}\n

                                            Congratulations! You have completed this tutorial.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/","title":"Tutorial: Setup for and use of ComplianceAsCode profile to OSCAL Catalog transformer","text":"

                                            Here are step by step instructions for setup and transformation of ComplianceAsCode profile data files into NIST standard OSCAL Catalog using the compliance-trestle tool.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/#objective","title":"Objective","text":"

                                            How to transform one or more .profile compliance files into a standardized OSCAL.json file.

                                            There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from .profile to OSCAL.json.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/#step-1-install-trestle-in-a-python-virtual-environment","title":"Step 1: Install trestle in a Python virtual environment","text":"

                                            Follow the instructions here to install trestle in a virtual environment.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/#step-2-transform-profile-data-cis-benchmarks","title":"Step 2: Transform profile data (CIS benchmarks)","text":"

                                            Linux, Mac

                                            Windows

                                            Make these changes:

                                            • use backslashes `\\` for file paths
                                            • use `md` instead of mkdir -p
                                            • put the url in double quotes for `curl`
                                            • use `more` instead of cat
                                            • Navigate to trestle workspace.
                                            (venv.trestle)$ cd trestle.workspace\n
                                            • View configuration information.
                                            (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-catalog -i\ntrestle.core.commands.task:102 WARNING: Config file was not configured with the appropriate section for the task: \"[task.ocp4-cis-profile-to-oscal-catalog]\"\nHelp information for ocp4-cis-profile-to-oscal-catalog task.\n\nPurpose: Create catalog from from standard (e.g. CIS benchmark).\n\nConfiguration flags sit under [task.ocp4-cis-profile-to-oscal-catalog]:\n  input-dir              = (required) location to read the compliance-as-code profile files.\n  output-dir             = (required) location to write the generated catalog.json file.\n  output-overwrite       = (optional) true [default] or false; replace existing output when true.\n
                                            • Create data folders.
                                            (venv.trestle)$ mkdir -p adjunct-data/cis-benchmarks\n(venv.trestle)$ mkdir -p adjunct-data/task-files\n
                                            • Fetch ComplianceAsCode profile data.
                                            (venv.trestle)$ curl 'https://raw.githubusercontent.com/ComplianceAsCode/content/master/products/ocp4/profiles/cis-node.profile' > adjunct-data/cis-benchmarks/cis-node.profile\n(venv.trestle)$ curl 'https://raw.githubusercontent.com/ComplianceAsCode/content/master/products/ocp4/profiles/cis-node.profile' > adjunct-data/cis-benchmarks/cis.profile\n
                                            • Fetch trestle task file.
                                            (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-catalog/demo-ocp4-cis-profile-to-oscal-catalog.config' > adjunct-data/task-files/demo-ocp4-cis-profile-to-oscal-catalog.config\n
                                            demo-ocp4-cis-profile-to-oscal-catalog.config
                                            [task.ocp4-cis-profile-to-oscal-catalog]\n\ninput-dir = adjunct-data/cis-benchmarks\noutput-dir = catalogs/ocp4-cis\n
                                            • Perform and validate the transform.
                                            (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-catalog -c adjunct-data/task-files/demo-ocp4-cis-profile-to-oscal-catalog.config\noutput: catalogs/ocp4-cis/catalog.json\nTask: ocp4-cis-profile-to-oscal-catalog executed successfully.\n\n(venv.trestle)$ trestle validate --all\nVALID: Model /home/<user>/trestle.workspace/catalogs/ocp4-cis/catalog.json passed the Validator to confirm the model passes all registered validation tests.\n
                                            • View the generated OSCAL.
                                            (venv.trestle)$ cat catlogs/ocp4-cis/catalog.json\n
                                            catalog.json
                                            {\n  \"catalog\": {\n    \"uuid\": \"19543ebf-4667-48b7-be47-d51154f16fda\",\n    \"metadata\": {\n      \"title\": \"CIS Red Hat OpenShift Container Platform 4 Benchmark\",\n      \"last-modified\": \"2021-12-03T13:52:21+00:00\",\n      \"version\": \"0.29.0\",\n      \"oscal-version\": \"1.0.0\",\n      \"links\": [\n        {\n          \"href\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis-node.profile\"\n        },\n        {\n          \"href\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile\"\n        }\n      ]\n    },\n    \"groups\": [\n      {\n        \"title\": \"1 Control Plane Components\",\n        \"groups\": [\n          {\n            \"title\": \"1.1 Master Node Configuration Files\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.1.1\",\n                \"title\": \"1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.2\",\n                \"title\": \"1.1.2 Ensure that the API server pod specification file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.3\",\n                \"title\": \"1.1.3 Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.4\",\n                \"title\": \"1.1.4 Ensure that the controller manager pod specification file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.5\",\n                \"title\": \"1.1.5 Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.6\",\n                \"title\": \"1.1.6 Ensure that the scheduler pod specification file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.7\",\n                \"title\": \"1.1.7 Ensure that the etcd pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.8\",\n                \"title\": \"1.1.8 Ensure that the etcd pod specification file ownership is set to root:root (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.1.9\",\n                \"title\": \"1.1.9 Ensure that the Container Network Interface file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.10\",\n                \"title\": \"1.1.10 Ensure that the Container Network Interface file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.11\",\n                \"title\": \"1.1.11 Ensure that the etcd data directory permissions are set to 700 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.12\",\n                \"title\": \"1.1.12 Ensure that the etcd data directory ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.13\",\n                \"title\": \"1.1.13 Ensure that the admin.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.14\",\n                \"title\": \"1.1.14 Ensure that the admin.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.15\",\n                \"title\": \"1.1.15 Ensure that the scheduler.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.16\",\n                \"title\": \"1.1.16 Ensure that the scheduler.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.17\",\n                \"title\": \"1.1.17 Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.18\",\n                \"title\": \"1.1.18 Ensure that the controller-manager.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.19\",\n                \"title\": \"1.1.19 Ensure that the OpenShift PKI directory and file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.20\",\n                \"title\": \"1.1.20 Ensure that the OpenShift PKI certificate file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.21\",\n                \"title\": \"1.1.21 Ensure that the OpenShift PKI key file permissions are set to 600\"\n              }\n            ]\n          },\n          {\n            \"title\": \"1.2 API Server\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.2.1\",\n                \"title\": \"1.2.1 Ensure that the --anonymous-auth argument is set to false\"\n              },\n              {\n                \"id\": \"CIS-1.2.2\",\n                \"title\": \"1.2.2 Ensure that the --basic-auth-file argument is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.3\",\n                \"title\": \"1.2.3 Ensure that the --token-auth-file parameter is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.4\",\n                \"title\": \"1.2.4 Ensure that the --kubelet-https argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.2.5\",\n                \"title\": \"1.2.5 Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.6\",\n                \"title\": \"1.2.6 Ensure that the --kubelet-certificate-authority argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.7\",\n                \"title\": \"1.2.7 Ensure that the --authorization-mode argument is not set to AlwaysAllow\"\n              },\n              {\n                \"id\": \"CIS-1.2.8\",\n                \"title\": \"1.2.8 Ensure that the --authorization-mode argument includes Node\"\n              },\n              {\n                \"id\": \"CIS-1.2.9\",\n                \"title\": \"1.2.9 Ensure that the --authorization-mode argument includes RBAC\"\n              },\n              {\n                \"id\": \"CIS-1.2.10\",\n                \"title\": \"1.2.10 Ensure that the admission control plugin EventRateLimit is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.11\",\n                \"title\": \"1.2.11 Ensure that the admission control plugin AlwaysAdmit is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.12\",\n                \"title\": \"1.2.12 Ensure that the admission control plugin AlwaysPullImages is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.13\",\n                \"title\": \"1.2.13 Ensure that the admission control plugin SecurityContextDeny is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.14\",\n                \"title\": \"1.2.14 Ensure that the admission control plugin ServiceAccount is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.15\",\n                \"title\": \"1.2.15 Ensure that the admission control plugin NamespaceLifecycle is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.16\",\n                \"title\": \"1.2.16 Ensure that the admission control plugin PodSecurityPolicy is set (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.2.17\",\n                \"title\": \"1.2.17 Ensure that the admission control plugin NodeRestriction is set (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.2.18\",\n                \"title\": \"1.2.18 Ensure that the --insecure-bind-address argument is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.19\",\n                \"title\": \"1.2.19 Ensure that the --insecure-port argument is set to 0\"\n              },\n              {\n                \"id\": \"CIS-1.2.20\",\n                \"title\": \"1.2.20 Ensure that the --secure-port argument is not set to 0\"\n              },\n              {\n                \"id\": \"CIS-1.2.21\",\n                \"title\": \"1.2.21 Ensure that the --profiling argument is set to false\"\n              },\n              {\n                \"id\": \"CIS-1.2.22\",\n                \"title\": \"1.2.22 Ensure that the --audit-log-path argument is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.23\",\n                \"title\": \"1.2.23 Ensure that the audit logs are forwarded off the cluster for retention\"\n              },\n              {\n                \"id\": \"CIS-1.2.24\",\n                \"title\": \"1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.25\",\n                \"title\": \"1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.26\",\n                \"title\": \"1.2.26 Ensure that the --request-timeout argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.27\",\n                \"title\": \"1.2.27 Ensure that the --service-account-lookup argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.2.28\",\n                \"title\": \"1.2.28 Ensure that the --service-account-key-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.29\",\n                \"title\": \"1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.30\",\n                \"title\": \"1.2.30 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.31\",\n                \"title\": \"1.2.31 Ensure that the --client-ca-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.32\",\n                \"title\": \"1.2.32 Ensure that the --etcd-cafile argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.33\",\n                \"title\": \"1.2.33 Ensure that the --encryption-provider-config argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.34\",\n                \"title\": \"1.2.34 Ensure that encryption providers are appropriately configured\"\n              },\n              {\n                \"id\": \"CIS-1.2.35\",\n                \"title\": \"1.2.35 Ensure that the API Server only makes use of Strong Cryptographic Ciphers\"\n              }\n            ]\n          },\n          {\n            \"title\": \"1.3 Controller Manager\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.3.1\",\n                \"title\": \"1.3.1 Ensure that garbage collection is configured as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.3.2\",\n                \"title\": \"1.3.2 Ensure that controller manager healthz endpoints are protected by RBAC. (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.3.3\",\n                \"title\": \"1.3.3 Ensure that the --use-service-account-credentials argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.3.4\",\n                \"title\": \"1.3.4 Ensure that the --service-account-private-key-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.3.5\",\n                \"title\": \"1.3.5 Ensure that the --root-ca-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.3.6\",\n                \"title\": \"1.3.6 Ensure that the RotateKubeletServerCertificate argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.3.7\",\n                \"title\": \"1.3.7 Ensure that the --bind-address argument is set to 127.0.0.1\"\n              }\n            ]\n          },\n          {\n            \"title\": \"1.4 Scheduler\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.4.1\",\n                \"title\": \"1.4.1 Ensure that the --profiling argument is set to false  (info only)\"\n              },\n              {\n                \"id\": \"CIS-1.4.2\",\n                \"title\": \"1.4.2 Ensure that the --bind-address argument is set to 127.0.0.1\"\n              }\n            ]\n          }\n        ]\n      },\n      {\n        \"title\": \"2 etcd\",\n        \"controls\": [\n          {\n            \"id\": \"CIS-2.1\",\n            \"title\": \"2.1 Ensure that the --cert-file and --key-file arguments are set as appropriate\"\n          },\n          {\n            \"id\": \"CIS-2.2\",\n            \"title\": \"2.2 Ensure that the --client-cert-auth argument is set to true\"\n          },\n          {\n            \"id\": \"CIS-2.3\",\n            \"title\": \"2.3 Ensure that the --auto-tls argument is not set to true\"\n          },\n          {\n            \"id\": \"CIS-2.4\",\n            \"title\": \"2.4 Ensure that the --peer-cert-file and --peer-key-file arguments are set as appropriate\"\n          },\n          {\n            \"id\": \"CIS-2.5\",\n            \"title\": \"2.5 Ensure that the --peer-client-cert-auth argument is set to true\"\n          },\n          {\n            \"id\": \"CIS-2.6\",\n            \"title\": \"2.6 Ensure that the --peer-auto-tls argument is not set to true\"\n          },\n          {\n            \"id\": \"CIS-2.7\",\n            \"title\": \"2.7 Ensure that a unique Certificate Authority is used for etcd\"\n          }\n        ]\n      },\n      {\n        \"title\": \"3 Control Plane Configuration\",\n        \"groups\": [\n          {\n            \"title\": \"3.1 Authentication and Authorization\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-3.1.1\",\n                \"title\": \"3.1.1 Client certificate authentication should not be used for users\"\n              }\n            ]\n          },\n          {\n            \"title\": \"3.2 Logging\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-3.2.1\",\n                \"title\": \"3.2.1 Ensure that a minimal audit policy is created\"\n              },\n              {\n                \"id\": \"CIS-3.2.2\",\n                \"title\": \"3.2.2 Ensure that the audit policy covers key security concerns\"\n              }\n            ]\n          }\n        ]\n      },\n      {\n        \"title\": \"4 Worker Nodes\",\n        \"groups\": [\n          {\n            \"title\": \"4.1 Worker node configuration\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-4.1.1\",\n                \"title\": \"4.1.1 Ensure that the kubelet service file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.2\",\n                \"title\": \"4.1.2 Ensure that the kubelet service file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-4.1.3\",\n                \"title\": \"4.1.3 If proxy kubeconfig file exists ensure permissions are set to 644 or more restrictive (Automated)\"\n              },\n              {\n                \"id\": \"CIS-4.1.4\",\n                \"title\": \"4.1.4 If proxy kubeconfig file exists ensure ownership is set to root:root (Manual)\"\n              },\n              {\n                \"id\": \"CIS-4.1.5\",\n                \"title\": \"4.1.5 Ensure that the --kubeconfig kubelet.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.6\",\n                \"title\": \"4.1.6 Ensure that the --kubeconfig kubelet.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-4.1.7\",\n                \"title\": \"4.1.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.8\",\n                \"title\": \"4.1.8 Ensure that the client certificate authorities file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-4.1.9\",\n                \"title\": \"4.1.9 Ensure that the kubelet --config configuration file has permissions set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.10\",\n                \"title\": \"4.1.10 Ensure that the kubelet configuration file ownership is set to root:root\"\n              }\n            ]\n          },\n          {\n            \"title\": \"4.2 Kubelet\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-4.2.1\",\n                \"title\": \"4.2.1 Ensure that the --anonymous-auth argument is set to false\"\n              },\n              {\n                \"id\": \"CIS-4.2.2\",\n                \"title\": \"4.2.2 Ensure that the --authorization-mode argument is not set to AlwaysAllow\"\n              },\n              {\n                \"id\": \"CIS-4.2.3\",\n                \"title\": \"4.2.3 Ensure that the --client-ca-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-4.2.4\",\n                \"title\": \"4.2.4 Ensure that the --read-only-port argument is set to 0\"\n              },\n              {\n                \"id\": \"CIS-4.2.5\",\n                \"title\": \"4.2.5 Ensure that the --streaming-connection-idle-timeout argument is not set to 0\"\n              },\n              {\n                \"id\": \"CIS-4.2.6\",\n                \"title\": \"4.2.6 Ensure that the --protect-kernel-defaults argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-4.2.7\",\n                \"title\": \"4.2.7 Ensure that the --make-iptables-util-chains argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-4.2.8\",\n                \"title\": \"4.2.8 Ensure that the --hostname-override argument is not set\"\n              },\n              {\n                \"id\": \"CIS-4.2.9\",\n                \"title\": \"4.2.9 Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture\"\n              },\n              {\n                \"id\": \"CIS-4.2.10\",\n                \"title\": \"4.2.10 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-4.2.11\",\n                \"title\": \"4.2.11 Ensure that the --rotate-certificates argument is not set to false\"\n              },\n              {\n                \"id\": \"CIS-4.2.12\",\n                \"title\": \"4.2.12 Verify that the RotateKubeletServerCertificate argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-4.2.13\",\n                \"title\": \"4.2.13 Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers\"\n              }\n            ]\n          }\n        ]\n      },\n      {\n        \"title\": \"5 Policies\",\n        \"groups\": [\n          {\n            \"title\": \"5.1 RBAC and Service Accounts\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.1.1\",\n                \"title\": \"5.1.1 Ensure that the cluster-admin role is only used where required\"\n              },\n              {\n                \"id\": \"CIS-5.1.2\",\n                \"title\": \"5.1.2 Minimize access to secrets (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.3\",\n                \"title\": \"5.1.3 Minimize wildcard use in Roles and ClusterRoles (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.4\",\n                \"title\": \"5.1.4 Minimize access to create pods (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.5\",\n                \"title\": \"5.1.5 Ensure that default service accounts are not actively used. (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.6\",\n                \"title\": \"5.1.6 Ensure that Service Account Tokens are only mounted where necessary (info)\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.2 Pod Security Policies / Security Context Constraints\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.2.1\",\n                \"title\": \"5.2.1 Minimize the admission of privileged containers (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.2\",\n                \"title\": \"5.2.2 Minimize the admission of containers wishing to share the host process ID namespace (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.3\",\n                \"title\": \"5.2.3 Minimize the admission of containers wishing to share the host IPC namespace (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.4\",\n                \"title\": \"5.2.4 Minimize the admission of containers wishing to share the host network namespace (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.5\",\n                \"title\": \"5.2.5 Minimize the admission of containers with allowPrivilegeEscalation (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.6\",\n                \"title\": \"5.2.6 Minimize the admission of root containers (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.7\",\n                \"title\": \"5.2.7 Minimize the admission of containers with the NET_RAW capability (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.8\",\n                \"title\": \"5.2.8 Minimize the admission of containers with added capabilities (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.9\",\n                \"title\": \"5.2.9 Minimize the admission of containers with capabilities assigned (info)\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.3 Network Policies and CNI\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.3.1\",\n                \"title\": \"5.3.1 Ensure that the CNI in use supports Network Policies (info)\"\n              },\n              {\n                \"id\": \"CIS-5.3.2\",\n                \"title\": \"5.3.2 Ensure that all Namespaces have Network Policies defined\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.4 Secrets Management\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.4.1\",\n                \"title\": \"5.4.1 Prefer using secrets as files over secrets as environment variables (info)\"\n              },\n              {\n                \"id\": \"CIS-5.4.2\",\n                \"title\": \"5.4.2 Consider external secret storage (info)\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.5 Extensible Admission Control\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.5.1\",\n                \"title\": \"5.5.1 Configure Image Provenance using ImagePolicyWebhook admission controller\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.6 General Policies\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.6.1\",\n                \"title\": \"5.6.1 Create administrative boundaries between resources using namespaces (info)\"\n              },\n              {\n                \"id\": \"CIS-5.6.2\",\n                \"title\": \"5.6.2 Ensure Seccomp Profile Pod Definitions (info)\"\n              },\n              {\n                \"id\": \"CIS-5.6.3\",\n                \"title\": \"5.6.3 Apply Security Context to your Pods and Containers (info)\"\n              },\n              {\n                \"id\": \"CIS-5.6.4\",\n                \"title\": \"5.6.4 The Default Namespace should not be used (info)\"\n              }\n            ]\n          }\n        ]\n      }\n    ]\n  }\n}\n

                                            Congratulations! You have completed this tutorial.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/","title":"Tutorial: Setup for and use of ComplianceAsCode profile to OSCAL Component Definition transformer","text":"

                                            Here are step by step instructions for setup and transformation of ComplianceAsCode profile data files into NIST standard OSCAL Component Definition using the compliance-trestle tool.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/#objective","title":"Objective","text":"

                                            How to transform one or more .profile compliance files into a standardized OSCAL.json file.

                                            There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from .profile to OSCAL.json.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/#step-1-install-trestle-in-a-python-virtual-environment","title":"Step 1: Install trestle in a Python virtual environment","text":"

                                            Follow the instructions here to install trestle in a virtual environment.

                                            "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/#step-2-transform-profile-data-cis-benchmarks","title":"Step 2: Transform profile data (CIS benchmarks)","text":"

                                            Linux, Mac

                                            Windows

                                            Make these changes:

                                            • use backslashes `\\` for file paths
                                            • use `md` instead of mkdir -p
                                            • put the url in double quotes for `curl`
                                            • use `more` instead of cat
                                            • Navigate to trestle workspace.
                                            (venv.trestle)$ cd trestle.workspace\n
                                            • View configuration information.
                                            (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-cd -i\ntrestle.core.commands.task:99 WARNING: Config file was not configured with the appropriate section for the task: \"[task.ocp4-cis-profile-to-oscal-cd]\"\nHelp information for ocp4-cis-profile-to-oscal-cd task.\n\nPurpose: Create component definition from standard (e.g. CIS benchmark).\n\nConfiguration flags sit under [task.ocp4-cis-profile-to-oscal-cd]:\n  component-name         = component name, e.g. OSCO.\n  org-name               = organization name, e.g. International Business Machines.\n  org-remarks            = organization remarks, e.g. IBM.\n  folder-cac             = folder containing compliance-as-code artifacts, e.g adjunct-data/cis-benchmarks/content.\n  output-dir             = location to write the generated component-definition.json file.\n  profile-name           = profile name, e.g. OCP4 CIS-benchmark v4.\n  profile-mnemonic       = profile mnemonic, e.g. ocp4-cis-node.\n  profile-ns             = profile ns, e.g. http://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud.\n  profile-version        = profile version, e.g. 1.1.\n  profile-check-version  = profile check version, e.g. 0.1.58.\n  profile-type           = profile type, e.g. OCP4.\n  profile-list           = profile list is blank separated list of \"<suffix>\" for config entries: profile-file.<suffix>, profile-title.<suffix>, profile-url.<suffix>, e.g. cis cis-node.\n  profile-file.<suffix>  = path of the profile file to ingest, e.g. ${folder-cac}/products/ocp4/profiles/cis-node.profile.\n  profile-title.<suffix> = title of the profile, e.g. CIS Red Hat OpenShift Container Platform 4 Benchmark.\n  profile-url.<suffix>   = URL of the profile, e.g. https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile.\n  rule-to-parameters-map = map file for set-parameters, e.g. adjunct-data/task-files/rule2var.json.\n  selected-rules         = file with list of selected rules, e.g. adjunct-data/task-files/selected_rules.json.\n  enabled-rules          = file with list of enabled rules, e.g. adjunct-data/task-files/enabled_rules.json.\n\nNotes:\n1. If a control has selected rules but no enabled rules, then all those selected are included.\n2. If a control has selected and enabled rules, then only those enabled are included.\n3. If a control has no selected rules, then none are included regardless of enabled.\n
                                            • Create data folders.
                                            (venv.trestle)$ mkdir -p adjunct-data/cis-benchmarks\n(venv.trestle)$ mkdir -p adjunct-data/config-files\n(venv.trestle)$ mkdir -p adjunct-data/task-files\n
                                            • Fetch ComplianceAsCode data.
                                            (venv.trestle)$ cd adjunct-data/cis-benchmarks/\n(venv.trestle)$ git clone https://github.com/ComplianceAsCode/content.git\n(venv.trestle)$ cd -\n
                                            • Fetch trestle config and task files.
                                            (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-cd/demo-ocp4-cis-profile-to-oscal-cd.config' > adjunct-data/config-files/demo-ocp4-cis-profile-to-oscal-cd.config\n(venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-cd/selected_rules.json' > adjunct-data/task-files/selected_rules.json\n(venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-cd/enabled_rules.json' > adjunct-data/task-files/enabled_rules.json\n
                                            demo-ocp4-cis-profile-to-oscal-cd.config
                                            [task.ocp4-cis-profile-to-oscal-cd]\n\ncomponent-name = OSCO\n\nfolder-cac = adjunct-data/cis-benchmarks/content\n\norg-name = International Business Machines\norg-remarks = IBM\n\noutput-dir = component-definitions/ocp4-cis\n\nprofile-name = OCP4 CIS-benchmark v4\nprofile-mnemonic = ocp4-cis-node\nprofile-ns = http://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\nprofile-version = 1.1\nprofile-check-version = 0.1.58\n\nprofile-type = OCP4\nprofile-list = cis-node cis\n\nprofile-file.cis-node = ${folder-cac}/products/ocp4/profiles/cis-node.profile\nprofile-url.cis-node = https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis-node.profile\nprofile-title.cis-node = CIS Red Hat OpenShift Container Platform 4 Benchmark\n\nprofile-file.cis = ${folder-cac}/products/ocp4/profiles/cis.profile\nprofile-url.cis = https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile\nprofile-title.cis = CIS Red Hat OpenShift Container Platform 4 Benchmark\n\nselected-rules  = adjunct-data/task-files/selected_rules.json\nenabled-rules  = adjunct-data/task-files/enabled_rules.json\n
                                            selected_rules.json
                                            [\n\"file_permissions_kube_apiserver\",\n\"file_owner_kube_apiserver\",\n\"file_groupowner_kube_apiserver\"\n]\n
                                            enabled_rules.json
                                            [\n\"file_permissions_cni_conf\",\n\"file_permissions_multus_conf\",\n\"file_owner_cni_conf\",\n\"file_groupowner_cni_conf\",\n\"file_owner_multus_conf\",\n\"file_groupowner_multus_conf\",\n\"kubelet_eviction_thresholds_set_soft_memory_available\",\n\"kubelet_eviction_thresholds_set_soft_nodefs_available\",\n\"kubelet_eviction_thresholds_set_soft_nodefs_inodesfree\",\n\"kubelet_eviction_thresholds_set_soft_imagefs_available\",\n\"kubelet_eviction_thresholds_set_soft_imagefs_inodesfree\",\n\"kubelet_eviction_thresholds_set_hard_memory_available\",\n\"kubelet_eviction_thresholds_set_hard_nodefs_available\",\n\"kubelet_eviction_thresholds_set_hard_nodefs_inodesfree\",\n\"kubelet_eviction_thresholds_set_hard_imagefs_available\",\n\"kubelet_eviction_thresholds_set_hard_imagefs_inodesfree\",\n\"etcd_unique_ca\",\n\"file_permissions_kubelet_conf\",\n\"file_groupowner_kubelet_conf\",\n\"file_owner_kubelet_conf\",\n\"file_permissions_worker_ca\",\n\"file_owner_worker_ca\",\n\"file_groupowner_worker_ca\",\n\"kubelet_anonymous_auth\",\n\"kubelet_configure_client_ca\",\n\"kubelet_enable_streaming_connections\",\n\"kubelet_enable_iptables_util_chains\",\n\"kubelet_disable_hostname_override\",\n\"kubelet_configure_event_creation\",\n\"kubelet_configure_tls_cipher_suites\"\n]\n
                                            • Perform and validate the transform.
                                            (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-cd -c adjunct-data/config-files/demo-ocp4-cis-profile-to-oscal-cd.config\noutput: component-definitions/ocp4-cis/component-definition.json\nTask: ocp4-cis-profile-to-oscal-cd executed successfully.\n\n(venv.trestle)$ trestle validate --all\nVALID: Model /home/<user>/trestle.workspace/component-definitions/ocp4-cis/component-definition.json passed the Validator to confirm the model passes all registered validation tests.\n
                                            • View the generated OSCAL.
                                            (venv.trestle)$ cat component-definitions/ocp4-cis/component-definition.json\n
                                            component-definition.json
                                            {\n\"component-definition\": {\n\"uuid\": \"d1b961ee-188b-42b9-943d-e11dc260f9dc\",\n\"metadata\": {\n\"title\": \"Component definition for OCP4 profiles\",\n\"last-modified\": \"2022-01-06T22:43:59+00:00\",\n\"version\": \"0.33.0\",\n\"oscal-version\": \"1.0.0\",\n\"roles\": [\n{\n\"id\": \"prepared-by\",\n\"title\": \"Indicates the organization that created this content.\"\n},\n{\n\"id\": \"prepared-for\",\n\"title\": \"Indicates the organization for which this content was created..\"\n},\n{\n\"id\": \"content-approver\",\n\"title\": \"Indicates the organization responsible for all content represented in the \\\"document\\\".\"\n}\n],\n\"parties\": [\n{\n\"uuid\": \"d00dff65-e4ae-4344-a206-1e298eff9066\",\n\"type\": \"organization\",\n\"name\": \"International Business Machines\",\n\"remarks\": \"IBM\"\n},\n{\n\"uuid\": \"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"type\": \"organization\",\n\"name\": \"Customer\",\n\"remarks\": \"organization to be customized at account creation only for their Component Definition\"\n},\n{\n\"uuid\": \"150f9eb7-7fa5-4989-b9be-bc3cba220354\",\n\"type\": \"organization\",\n\"name\": \"ISV\",\n\"remarks\": \"organization to be customized at ISV subscription only for their Component Definition\"\n}\n],\n\"responsible-parties\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n},\n\"components\": [\n{\n\"uuid\": \"e2ee2b93-6103-42de-b615-65b0b3ff2dc4\",\n\"type\": \"Service\",\n\"title\": \"OSCO\",\n\"description\": \"OSCO\",\n\"control-implementations\": [\n{\n\"uuid\": \"f9c2699a-2d2c-4ee2-87f3-042d1a9b3a79\",\n\"source\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis-node.profile\",\n\"description\": \"OSCO implemented controls for CIS Red Hat OpenShift Container Platform 4 Benchmark.\",\n\"props\": [\n{\n\"name\": \"profile_name\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"OCP4 CIS-benchmark v4\",\n\"class\": \"scc_profile_name\"\n},\n{\n\"name\": \"profile_mnemonic\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"ocp4-cis-node\",\n\"class\": \"scc_profile_mnemonic\"\n},\n{\n\"name\": \"profile_version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"1.1\",\n\"class\": \"scc_profile_version\"\n},\n{\n\"name\": \"profile_check_version\",\n\"value\": \"0.1.58\"\n}\n],\n\"implemented-requirements\": [\n{\n\"uuid\": \"97142b13-bc30-4e72-be7f-36de9149a679\",\n\"control-id\": \"CIS-1.1.1\",\n\"description\": \"Ensure that the API server pod specification file permissions are set to 644 or more restrictive\",\n\"props\": [\n{\n\"name\": \"XCCDF_rule\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"xccdf_org.ssgproject.content_rule_file_permissions_kube_apiserver\",\n\"class\": \"scc_goal_name_id\",\n\"remarks\": \"Verify Permissions on the Kubernetes API Server Pod Specification File\"\n}\n],\n\"responsible-roles\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n},\n{\n\"uuid\": \"0690e2a7-b228-4954-93fe-c1d55936cfa8\",\n\"control-id\": \"CIS-1.1.2\",\n\"description\": \"Ensure that the API server pod specification file ownership is set to root:root\",\n\"props\": [\n{\n\"name\": \"XCCDF_rule\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"xccdf_org.ssgproject.content_rule_file_owner_kube_apiserver\",\n\"class\": \"scc_goal_name_id\",\n\"remarks\": \"Verify User Who Owns The Kubernetes API Server Pod Specification File\"\n}\n],\n\"responsible-roles\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n},\n{\n\"uuid\": \"18c61fb2-8603-440d-9d9a-8d6d1e232cd3\",\n\"control-id\": \"CIS-1.1.2\",\n\"description\": \"Ensure that the API server pod specification file ownership is set to root:root\",\n\"props\": [\n{\n\"name\": \"XCCDF_rule\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"xccdf_org.ssgproject.content_rule_file_groupowner_kube_apiserver\",\n\"class\": \"scc_goal_name_id\",\n\"remarks\": \"Verify Group Who Owns The Kubernetes API Server Pod Specification File\"\n}\n],\n\"responsible-roles\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n}\n]\n}\n]\n}\n]\n}\n}\n

                                            Congratulations! You have completed this tutorial.

                                            "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/","title":"Tutorial: Setup for and use of Tanium to OSCAL transformer","text":"

                                            Here are step by step instructions for setup and transformation of Tanium compliance data files into NIST standard OSCAL using the compliance-trestle tool.

                                            "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/#objective","title":"Objective","text":"

                                            How to transform a Tanium.results compliance file into a standardized OSCAL.json file.

                                            There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from Tanium.results to OSCAL.json.

                                            "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/#step-1-environment-setup","title":"Step 1: Environment setup","text":"

                                            Linux, Mac

                                            Windows

                                            Make these changes:

                                            • use backslashes `\\` for file paths
                                            • use `md` instead of mkdir -p
                                            • put the url in double quotes for `curl`
                                            • use `more` instead of cat
                                            • Insure you have a modern Python (3.7, 3.8, 3.9).
                                            $ python -V\nPython 3.8.3\n
                                            • Setup a virtual environment.
                                            $ cd\n$ python -m venv venv.trestle\n$ source venv.trestle/bin/activate\n(venv.trestle)$\n
                                            • Insure you have a modern pip (19.x or greater).
                                            (venv.trestle)$ pip --version\npip 19.2.3 from /home...\n
                                            • Install compliance-trestle.
                                            (venv.trestle)$ pip install compliance-trestle\nLooking in indexes: https://pypi.org/simple,...\n
                                            • Check trestle viability (and view help).
                                            (venv.trestle)$ trestle -h\nusage: trestle [-h] {init,create,split,merge,replicate,add,remove,validate,import,task,assemble} ...\n
                                            • Create trestle workspace.
                                            (venv.trestle)$ mkdir trestle.workspace\n(venv.trestle)$ cd trestle.workspace\n(venv.trestle)$ trestle init\nInitialized trestle project successfully in /home/<user>/trestle.workspace\n
                                            "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/#step-2-transform-sample","title":"Step 2: Transform sample","text":"
                                            • Create Tanium data folders.
                                            (venv.trestle)$ mkdir -p tanium/tests/data/tasks/tanium/input\n
                                            • Fetch sample Tanium data file. It is a \"raw\" Tanium result for which a transformation to OSCAL is desired.
                                            (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/develop/tests/data/tasks/tanium/input-doc/Tanium.doc-json' > tanium/tests/data/tasks/tanium/input/Tanium.doc-json\n
                                            sample: Tanium.doc-json
                                            {\n\"Computer Name\": \"RHEL8\",\n\"Tanium Client IP Address\": \"192.168.0.125\",\n\"IP Address\": [\n\"192.168.0.125\",\n\"192.168.122.1\",\n\"fe80::3c47:1aff:fe33:601\"\n],\n\"Comply - Compliance Findings\": [\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"State\": \"notchecked\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\"\n}\n],\n\"Count\": \"1\"\n}\n
                                            • Fetch sample trestle tanium-result-to-oscal-ar config file. It informs the trestle command where to read input and write output.
                                            (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/develop/tests/data/tasks/tanium/demo-tanium-result-to-oscal-ar.config' > tanium/demo-tanium-result-to-oscal-ar.config\n
                                            sample: demo-tanium-result-to-oscal-ar.config
                                            [task.tanium-result-to-oscal-ar]\n\ninput-dir =  tests/data/tasks/tanium/input\noutput-dir = tests/data/tasks/tanium/runtime\n
                                            • Perform the transform.
                                            (venv.trestle)$ cd tanium\n(venv.trestle)$ trestle task tanium-result-to-oscal-ar -c demo-tanium-result-to-oscal-ar.config \ninput: tests/data/tasks/tanium/input/Tanium.doc-json\noutput: tests/data/tasks/tanium/runtime/Tanium.oscal.json\ninventory: 1\nobservations: 9\nTask: tanium-result-to-oscal-ar executed successfully.\n
                                            • View the generated OSCAL.
                                            (venv.trestle)$ cat tests/data/tasks/tanium/runtime/Tanium.oscal.json\n
                                            sample: Tanium.oscal.json
                                            {\n\"results\": [\n{\n\"uuid\": \"f79add8e-488a-45f3-9024-72ecf95c7952\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-05-12T13:46:46.000+00:00\",\n\"end\": \"2021-05-12T13:46:46.000+00:00\",\n\"local-definitions\": {\n\"components\": {\n\"1ea447fe-a2af-4110-baae-c70ed5223261\": {\n\"type\": \"Operating System\",\n\"title\": \"Red Hat Enterprise Linux 8\",\n\"description\": \"Red Hat Enterprise Linux 8\",\n\"status\": {\n\"state\": \"operational\"\n}\n}\n},\n\"inventory-items\": [\n{\n\"uuid\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"Computer Name\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"RHEL8\"\n},\n{\n\"name\": \"Tanium Client IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"192.168.0.125\",\n\"class\": \"scc_inventory_item_id\"\n},\n{\n\"name\": \"IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"['192.168.0.125', '192.168.122.1', 'fe80::3c47:1aff:fe33:601']\"\n},\n{\n\"name\": \"Count\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1\"\n}\n],\n\"implemented-components\": [\n{\n\"component-uuid\": \"1ea447fe-a2af-4110-baae-c70ed5223261\"\n}\n]\n}\n]\n},\n\"reviewed-controls\": {\n\"control-selections\": [\n{}\n]\n},\n\"observations\": [\n{\n\"uuid\": \"e67f5fd9-5b1f-4134-a67e-cebdc2e5735c\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"6cb81459-9c25-4a8b-bf3c-d8ff08ee728c\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"9453eaed-db41-4a20-b684-2887de2d9657\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"a37c2569-8695-4cfe-8b5c-bd8d6eaf9df7\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"b77e1b49-a818-4d43-adaf-69effcbd9219\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"ac25b329-7a4a-45f4-b42b-1cce470e237b\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"f9c0f033-f08b-431d-b411-fe1f63c2c98c\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"149a814e-7f80-4e6d-a613-54f027e0d663\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"a0e602b5-e587-41c5-846b-675b26cf3e18\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"notchecked\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n}\n],\n\"findings\": [\n{\n\"uuid\": \"00000000-0000-4000-8000-000000000000\",\n\"title\": \"No Finding.\",\n\"description\": \"No Finding.\"\n}\n]\n}\n]\n}\n

                                            Congratulations! You have bridged Tanium data into an OSCAL Assessment Results using compliance-trestle.

                                            Newtown, Victoria

                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/","title":"Tutorial: How to build an Oscal Assessment Results \"lite\" with Trestle SDK from your posture result format","text":"

                                            The compliance-trestle (trestle) project provides helpful modules to assist your standardization efforts. Discussed below are some best practices for automated bridging to NIST OSCAL.

                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#why-nist-oscal","title":"Why NIST OSCAL?","text":"

                                            The Open Security Controls Assessment Language OSCAL is a set of formats expressed in XML, JSON, and YAML that provide machine-readable representations of control catalogs, control baselines, system security plans, and assessment plans and results as adopted by the National Institute of Standards and Technology NIST.

                                            Standardizing to OSCAL facilitates data interchange and understandability.

                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#objective","title":"Objective","text":"

                                            The objective here is to transform your compliance data into valid OSCAL, in particular System Assessment Results SAR.

                                            Examples of existing transformers included with trestle are for the OpenShift Compliance Operator OSCO and Tanium.

                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#overview","title":"Overview","text":"

                                            You have a source of compliance data that is in non-OSCAL format (spreadsheet, XML, JSON, database, object-store...) and you would like to transform into standardized form in terms of NIST OSCAL. Presumed is an existing method for obtaining the compliance data from the cloud and materializing on disk as one or more files.

                                            • Source files on disk (pink) is our starting point.
                                            • OSCAL files on disk (blue) is our ending point.
                                            • OSCAL object management and emitter Python code are provided by trestle (green).
                                            • Transformation Python code (yellow) is to be written by you.

                                            Other possible code stack configurations (not shown):

                                            • write your own command module (file interface), but use trestle logic module (data processing)
                                            • write your own command and logic modules, but rely on trestle OSCAL support and base

                                            For example, one could create an auditree-arboretum harvest report (file interface) that employs the trestle xccdf-result-to-oscal-ar transformation (data processing) module.

                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#choose-mapping-strategy","title":"Choose Mapping Strategy","text":"

                                            There are 3 potential levels of OSCAL Assessment Results that can be emitted by your transformer. From most complex to least complex they are:

                                            • a complete SAR
                                            • a partial SAR comprising Findings with Observations
                                            • a partial SAR comprising Observations only

                                            Below is a snippet from the SAR model with these three levels shown.

                                            Although producing a complete SAR is possible, this transformation is not covered here. We focus on partial results, either Observations only or Observations with Findings.

                                            Based on the data in hand from your compliance data source, and additional metadata that can be made available at the time of transformation, choose the best fit.

                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#observations-only","title":"Observations only","text":"

                                            Emitting Observations only requires just rudimentary source data. For example, if each instance of source data includes not much more than:

                                            • inventory-name: ssg-ocp4-ds-cis-111.222.333.444-pod
                                            • rule-name: xccdf_org.ssgproject.content_rule_scheduler_profiling_argument
                                            • rule-result: fail

                                            then the best mapping would be to an Observations only.

                                            example snippet: instance suitable for mapping to Observation
                                            data: <rule-result idref=\"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\"\ntime=\"2020-08-03T02:26:26+00:00\" severity=\"low\" weight=\"1.000000\"> <result>fail</result>\n</rule-result>\nmetadata:\nname: ssg-ocp4-ds-cis-111.222.333.444-pod\n
                                            example snippet: instance OSCAL Observation
                                            {\n\"uuid\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"title\": \"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\",\n\"description\": \"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\",\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"type\": \"component\",\n\"title\": \"Red Hat OpenShift Kubernetes\"\n},\n{\n\"uuid-ref\": \"46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\",\n\"type\": \"inventory-item\",\n\"title\": \"Pod\",\n\"props\": [\n{\n\"name\": \"target\",\n\"value\": \"kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\"\n},\n{\n\"name\": \"cluster-name\",\n\"value\": \"ROKS-OpenSCAP-1\"\n},\n{\n\"name\": \"cluster-type\",\n\"value\": \"openshift\"\n},\n{\n\"name\": \"cluster-region\",\n\"value\": \"us-south\"\n}\n]\n}\n],\n\"relevant-evidence\": [\n{\n\"href\": \"https://github.mycorp.com/degenaro/evidence-locker\",\n\"description\": \"Evidence location.\",\n\"props\": [\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"id\",\n\"value\": \"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\"\n},\n{\n\"name\": \"time\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"timestamp\",\n\"value\": \"2020-08-03T02:26:26+00:00\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"result\",\n\"value\": \"fail\"\n},\n{\n\"name\": \"target\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"target\",\n\"value\": \"kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\"\n}\n]\n}\n]\n}\n
                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#findings-with-observations","title":"Findings with Observations","text":"

                                            To additionally produce Findings, information about the controls associated with each rule-name is required. The control information can be part of the source data itself or can be provided as one or more supplemental metadata files.

                                            If each instance of source data includes:

                                            • inventory-name: cmp-wn-2115.demo.tanium.local
                                            • rule-name: xccdf_org.cisecurity.benchmarks_rule_19.7.44.2.1_L2_Ensure_Prevent_Codec_Download_is_set_to_Enabled
                                            • rule-result: fail
                                            • control-name: 800-53: SC-18

                                            then the best mapping wound be to Findings with Observations.

                                            example snippet: xml instance suitable for mapping to Finding with Observation
                                            {\n\"IP Address\": \"10.8.68.218\",\n\"Computer Name\": \"cmp-wn-2115.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_19.7.44.2.1_L2_Ensure_Prevent_Codec_Download_is_set_to_Enabled\",\n\"Result\": \"fail\",\n\"Custom ID\": \"800-53: SC-18\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
                                            example snippet: instance OSCAL Finding
                                            {\n\"findings\": [\n{\n\"uuid\": \"99c0a0de-e34e-4e22-95a1-1d4f24826565\",\n\"title\": \"800-53: IA-5\",\n\"description\": \"800-53: IA-5\",\n\"collected\": \"2021-03-16T13:29:14.000+00:00\",\n\"objective-status\": {\n\"props\": [\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"class\": \"source\",\n\"value\": \"NIST 800-53\"\n},\n{\n\"name\": \"id-ref\",\n\"ns\": \"dns://tanium\",\n\"class\": \"source\",\n\"value\": \"IA-5\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"STRVALUE\",\n\"value\": \"FAIL\"\n}\n],\n\"status\": \"not-satisfied\"\n},\n\"related-observations\": [\n{\n\"observation-uuid\": \"61092735-e365-4638-bc2c-ecd0ed407e73\"\n},\n{\n\"observation-uuid\": \"95a20b8e-ed0a-4b6c-bf87-8789265c7158\"\n}\n]\n}\n]\n}\n
                                            example snippet: instance OSCAL Observation
                                            {\n\"observations\": [\n{\n\"uuid\": \"61092735-e365-4638-bc2c-ecd0ed407e73\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"class\": \"source\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"id\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"result\",\n\"value\": \"pass\"\n},\n{\n\"name\": \"time\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"timestamp\",\n\"value\": \"2021-03-16T13:29:14+00:00\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2650b9ba-e767-4381-9a3f-127d1552d7d2\",\n\"type\": \"inventory-item\"\n}\n]\n}\n]\n}\n
                                            example snippet: local definitions
                                            {\n\"results\": [\n{\n\"uuid\": \"98028241-8705-4211-bf36-71e1f7aa6192\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-03-16T13:29:14.000+00:00\",\n\"local-definitions\": {\n\"inventory-items\": [\n{\n\"uuid\": \"2650b9ba-e767-4381-9a3f-127d1552d7d2\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"computer-name\",\n\"ns\": \"dns://tanium\",\n\"class\": \" inventory-item\",\n\"value\": \"cmp-wn-2106.demo.tanium.local\"\n},\n{\n\"name\": \"computer-ip\",\n\"ns\": \"dns://tanium\",\n\"class\": \" inventory-item\",\n\"value\": \"fe80::3cd5:564b:940e:49ab\"\n},\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"class\": \" inventory-item\",\n\"value\": \"Windows 10\"\n}\n]\n}\n]\n}\n}\n]\n}\n
                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#implement-mapping-strategy","title":"Implement Mapping Strategy","text":"

                                            The best practice for building a transformer is to employ layers. Recall that the top two layers (in yellow) are for you to implement, while the bottom two layers (in green) are provided by trestle to assist you.

                                            Trestle is a Python based multi-faceted platform that simplifies this task by providing a set of Python classes which enforce adherence to the OSCAL schema, insuring that the produced OSCAL validates.

                                            • file interfacing (read/write files)
                                            • data processing (in-memory object structure construction)
                                            • use of OSCAL versioned platform objects (trestle base and oscal functionality)
                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#file-interfacing","title":"File Interfacing","text":"

                                            Write a command line tool, for example a trestle task or auditree-arboretum harvest report that:

                                            • imports the commensurate data processing module
                                            • reads the input
                                            • send input to data processing module
                                            • receives transformed data from data processing module
                                            • writes the output
                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#data-processing","title":"Data Processing","text":"

                                            Write a data processing module that receives data, and optionally metadata, for transformation from native form into OSCAL. Separation from the command line file read/write mechanism allows for module re-use.

                                            The module should:

                                            • import the trestle oscal module
                                            • receive input data to be transformed
                                            • receive metadata, optionally
                                            • transform input into trestle oscal classes hierarchy
                                            • send transformed OSCAL data in return

                                            For the Observation only case, the transform is straight forward. Code should create one Observation for each rule/result pair.

                                            For the Findings case, a bit more logic is required. Code should accumulate Observations for each Finding and determine an overall status for it. For example, if 15 Observations are found for Finding control AC-3, where 14 have result=PASS and 1 has result=FAIL, then the overall status for the Finding would be not satisfied with overall result=FAIL.

                                            "},{"location":"tutorials/task.transformer-construction/transformer-construction/#examples","title":"Examples","text":"

                                            There are 2 transformers in trestle. The xccdf-result-to-oscal-ar transformer emits OSCAL Observations, the simplest partial result.

                                            The tanium-result-to-oscal-ar transformer emits OSCAL Findings, a more complex partial result.

                                            Table of approximate lines of code.

                                            task-name OSCAL type file interface data processing test cases xccdf-result-to-oscal-ar Observations only 275 350 400 tanum-to-oscal Findings, with Observations 200 350 300"},{"location":"tutorials/task.transformer-construction/transformer-construction/#contributing","title":"Contributing","text":"

                                            Consider contributing your transformer to trestle or auditree-arboretum or other appropriate open source repository.

                                            "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Compliance-trestle (also known as trestle)","text":"

                                            Trestle is an ensemble of tools that enable the creation, validation, and governance of documentation artifacts for compliance needs. It leverages NIST's OSCAL as a standard data format for interchange between tools and people, and provides an opinionated approach to OSCAL adoption.

                                            Trestle is designed to operate as a CICD pipeline running on top of compliance artifacts in git, to provide transparency for the state of compliance across multiple stakeholders in an environment friendly to developers. Trestle passes the generated artifacts on to tools that orchestrate the enforcement, measurement, and reporting of compliance.

                                            It also provides tooling to manage OSCAL documents in a more human-friendly manner. By splitting large OSCAL data structures into smaller and easier to edit sub-structures, creation and maintenance of these artifacts can follow normal git workflows including peer review via pull request, versioning, releases/tagging.

                                            Trestle provides three separate but related functions in the compliance space:

                                            • Manage OSCAL documents to allow editing and manipulation while making sure the schemas are enforced
                                            • Transform documents from other formats to OSCAL
                                            • Provide support and governance to author compliance content as markdown and drawio.

                                            Trestle provides tooling to help orchestrate the compliance process across a number of dimensions:

                                            • Help manage OSCAL documents in a more human-friendly manner by expanding the large OSCAL data structures into smaller and easier to edit sub-structures while making sure the schemas are enforced.
                                            • Transform documents from other formats to OSCAL
                                            • Provide governance for markdown documents and enforce consistency of format and content based on specified templates
                                            • Tooling manage authoring and governance of markdown and drawio files withn a repository.
                                            • Support within trestle to streamline management within a managed git environment.
                                            • An underlying object model that supports developers interacting with OSCAL artefacts.
                                            "},{"location":"#important-note","title":"Important Note:","text":"

                                            The current version of trestle supports NIST OSCAL 1.0.0-4. There was a breaking change in OSCAL moving from version 1.0.0 to 1.0.2 mainly due to prop becoming props in AssessmentResults. As a result, the current development path of trestle requires OSCAL 1.0.4, but for those who require OSCAL 1.0.0 please use trestle version 0.37.x. That version is stable but will not have any features added, and we encourage users to move to OSCAL 1.0.4.

                                            OSCAL version 1.0.0 files are still handled on import but any AssessmentResults must conform to the OSCAL 1.0.4 schema, with props instead of prop. And all files created by trestle will be output as OSCAL version 1.0.4.

                                            "},{"location":"#why-trestle","title":"Why Trestle","text":"

                                            Compliance suffers from being a complex topic that is hard to articulate simply. It involves complete and accurate execution of multiple procedures across many disciplines (e.g. IT, HR, management) with periodic verification and audit of those procedures against controls.

                                            While it is possible to manage the description of controls and how an organisation implements them in ad hoc ways with general tools (spreadsheets, documents), this is hard to maintain for multiple accreditations and, in the IT domain at least, creates a barrier between the compliance efforts and the people doing daily work (DevOps staff).

                                            Trestle aims to reduce or remove this barrier by bringing the maintenance of control descriptions into the DevOps domain. The goal is to have changes to the system (for example, updates to configuration management) easily related to the controls impacted, and to enable modification of those controls as required in concert with the system changes.

                                            Trestle implicitly provides a core opinionated workflow driven by its pipeline to allow standardized interlocks with other compliance tooling platforms.

                                            "},{"location":"#machine-readable-compliance-format","title":"Machine readable compliance format","text":"

                                            Compliance activities at scale, whether size of estate or number of accreditations, require automation to be successful and repeatable. OSCAL as a standard allows teams to bridge between the \"Governance\" layer and operational tools.

                                            By building human managed artifacts into OSCAL, Trestle is not only able to validate the integrity of the artifacts that people generate - it also enables reuse and sharing of artifacts, and furthermore can provide suitable input into tools that automate operational compliance.

                                            "},{"location":"#supported-oscal-elements-and-extensions","title":"Supported OSCAL elements and extensions","text":"

                                            trestle implicitly supports all OSCAL schemas for use within the object model. The development roadmap for trestle includes adding workflow around specific elements / objects that is opinionated.

                                            "},{"location":"#supported-file-formats-for-oscal-objects","title":"Supported file formats for OSCAL objects.","text":"

                                            OSCAL supports xml, json and yaml with their metaschema tooling. Trestle natively supports only json and yaml formats at this time.

                                            Future roadmap anticipates that support for xml import and upstream references will be enabled. However, it is expected that full support will remain only for json and yaml.

                                            Users needing to import XML OSCAL artifacts are recommended to look at NIST's XML to json conversion page here.

                                            "},{"location":"#python-codebase-easy-installation-via-pip","title":"Python codebase, easy installation via pip","text":"

                                            Trestle runs on most all python platforms (e.g. Linux, Mac, Windows) and is available on PyPi so it is easily installed via pip. It is under active development and new releases are made available regularly.

                                            "},{"location":"#development-status","title":"Development status","text":"

                                            Compliance trestle is currently stable and is based on NIST OSCAL version 1.0.4, with active development continuing.

                                            "},{"location":"#contributing-to-trestle","title":"Contributing to Trestle","text":"

                                            Our project welcomes external contributions. Please consult contributing to get started.

                                            "},{"location":"#license-authors","title":"License & Authors","text":"

                                            If you would like to see the detailed LICENSE click here. Consult contributors for a list of authors and maintainers for the core team.

                                            # Copyright (c) 2020 IBM Corp. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n
                                            "},{"location":"cli/","title":"trestle CLI Overview and OSCAL Usecases","text":"

                                            The trestle CLI has three primary use cases:

                                            • Serve as tooling to generate and manipulate OSCAL files directly by an end user. The objective is to reduce the complexity of creating and editing workflows. Example commands are: trestle import, trestle create, trestle split, trestle merge.
                                            • Act as an automation tool that, by design, can be an integral part of a CI/CD pipeline e.g. trestle validate, trestle tasks.
                                            • Allow governance of markdown documents so they conform to specific style or structure requirements.

                                            To support each of these use cases trestle creates an opinionated directory structure to manage governed documents.

                                            "},{"location":"cli/#opinionated-directory-structure","title":"Opinionated directory structure","text":"

                                            Trestle relies on an opinionated directory structure (trestle workspace), similar to git, go, or auditree, to manage the workflow. Most trestle commands are restricted to working within an initialized directory tree.

                                            The directory structure setup by trestle has three major elements:

                                            • A .trestle hidden folder.
                                            • A dist folder.
                                            • Folders for each of the top level OSCAL models.

                                            The outline of the schema is below:

                                            .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 dist\n\u2502   \u251c\u2500\u2500 catalogs\n\u2502   \u251c\u2500\u2500 profiles\n\u2502   \u251c\u2500\u2500 component-definitions\n\u2502   \u251c\u2500\u2500 system-security-plans\n\u2502   \u251c\u2500\u2500 assessment-plans\n\u2502   \u251c\u2500\u2500 assessment-results\n\u2502   \u2514\u2500\u2500 plan-of-action-and-milestones\n\u251c\u2500\u2500 catalogs\n\u251c\u2500\u2500 profiles\n\u251c\u2500\u2500 component-definitions\n\u251c\u2500\u2500 system-security-plans\n\u251c\u2500\u2500 assessment-plans\n\u251c\u2500\u2500 assessment-results\n\u2514\u2500\u2500 plan-of-action-and-milestones\n

                                            .trestle directory is a special directory containing various trestle artefacts to help run various other commands. Examples include configuration files, caches and templates.

                                            dist directory will contain the assembled version of the top level models located on the source model directories.

                                            The bulk of the folder structure is used to represent each of the top level schemas or top level models such as catalogs and profiles. For each of these directories the following root structure is maintained:

                                            \u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 TOP_LEVEL_MODEL_PLURAL\n    \u2514\u2500\u2500 NAME_OF_MODEL_INSTANCE\n        \u2514\u2500\u2500 TOP_LEVEL_MODEL_NAME.{json,yaml,yml}\n

                                            which appears, for a catalog a user decides is titled nist-800-53, as:

                                            \u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 nist-800-53\n        \u2514\u2500\u2500 catalog.json\n

                                            In most of the places in the documentation we use json format for specifying model files, but they are equally applicable to yaml format also. The default format is json, and yaml is supported on best effort basis. Within one model directory the two different formats should not be mixed.

                                            "},{"location":"cli/#support-for-subdivided-document-structures","title":"Support for subdivided document structures","text":"

                                            The files constructed by OSCAL can run into tens of thousands of lines of yaml or formatted json. At this size the files become completely unmanageable for users. To combat this, trestle can trestle split a file into many smaller files and later merge those split files together.

                                            Directory structures such as the one below can represent OSCAL document structures. Users are strongly encourage to rely on split and merge to code these structures.

                                            Users can query the contents of files using trestle describe, and probe the contents more deeply using it in combination with element paths.

                                            .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 dist \n\u2502   \u2514\u2500\u2500 catalogs\n\u2502       \u2514\u2500\u2500 nist800-53.json \n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 nist800-53\n        \u251c\u2500\u2500 catalog.json\n        \u2514\u2500\u2500 catalog\n            \u251c\u2500\u2500 metadata.json\n            \u251c\u2500\u2500 metadata\n            \u2502   \u251c\u2500\u2500 revision-history\n            \u2502   \u2502   \u251c\u2500\u2500 00000__revision-history.json\n            \u2502   \u2502   \u251c\u2500\u2500 00001__revision-history.json\n            \u2502   \u2502   \u2514\u2500\u2500 00002__revision-history.json   \n            \u2502   \u2514\u2500\u2500 responsible-parties\n            \u2502       \u251c\u2500\u2500 creator__responsible-party.json\n            \u2502       \u2514\u2500\u2500 contact__responsible-party.json       \n            \u2514\u2500\u2500 groups\n                \u251c\u2500\u2500 00000__group.json        \n                \u251c\u2500\u2500 00000__group\n                \u2502   \u2514\u2500\u2500 controls\n                \u2502       \u251c\u2500\u2500 00000__control.json\n                \u2502       \u2514\u2500\u2500 00001__control.json\n                \u251c\u2500\u2500 00001__group.json \n                \u2514\u2500\u2500 00001__group\n                    \u2514\u2500\u2500 controls\n                        \u251c\u2500\u2500 00000__control.json\n                        \u2514\u2500\u2500 00001__control.json\n...\n
                                            "},{"location":"cli/#specifying-attributes-elements-within-trestle-commands","title":"Specifying attributes / elements within trestle commands.","text":"

                                            OSCAL models are rich and contain multiple nested data structures. Given this, a mechanism is required to address elements /attributes within an oscal object.

                                            This accessing method is called 'element path' and is similar to jsonPath. Commands provide element path by a -e argument where available, e.g. trestle split -f catalog.json -e 'catalog.metadata.*'. This path is used whenever specifying an attribute or model, rather than exposing trestle's underlying object model name. Users can refer to NIST's json outline to understand object names in trestle.

                                            "},{"location":"cli/#rules-for-element-path","title":"Rules for element path","text":"
                                            1. Element path is an expression of the attribute names, in json form , concatenated by a period (.).
                                            2. E.g. The metadata in a catalog is referred to as catalog.metadata
                                            3. Element paths are relative to the file.
                                            4. e.g. For metadata.json roles would be referred to as metadata.roles, from the catalog file that would be catalog.metadata.roles
                                            5. Arrays can be handled by a wild card * or a numerical index for a specific index.
                                            6. catalog.groups.* to refer to each group in a catalog
                                            7. catalog.groups.*.controls.* to refer to 'for each control under a top level group'
                                            8. For NIST 800-53 catalog.groups.0.controls.0.
                                            9. On *nix platforms if using the wildcard the element path argument should be wrapped in quotes to prevent problems with the shell interpreting the wild card before trestle can
                                            10. When dealing with an array based object, the array syntax may be skipped when passing a model
                                            11. e.g. a control could be catalog.controls.control or catalog.groups.controls.control
                                            12. This syntax is required as OSCAL, across the schema, has conflicting element definitions.
                                            "},{"location":"cli/#a-note-for-software-developers-using-trestle","title":"A note for software developers using trestle.","text":"

                                            Trestle provides utilities for converting from element path to trestle's python object model. The (slightly simplified) model is:

                                            1. Class attributes are converted from dash-case to dash_case (aka snake_case)
                                            2. Class names are converted from dash-case to DashCase (aka CamelCase)
                                            "},{"location":"cli/#trestle-version","title":"trestle version","text":"

                                            This command will return the current version of Trestle and OSCAL it is using.

                                            Running trestle version will return:

                                            Trestle version v2.0.0 based on OSCAL version 1.0.4

                                            It can also be used to retrieve the metadata version of the OSCAL object:

                                            \"catalog\": {\n\n\"uuid\": \"fa3f44a8-25cd-4f6a-8175-7afe647df7ed\",\n\n\"metadata\": {\n\n\"title\": \"Catalog1\",\n\n\"last-modified\": \"2023-01-11T17:04:02.840910+00:00\",\n\n\"version\": \"0.1.10\", <<< this version here\n\n\"oscal-version\": \"1.0.4\"\n\n},\n...\n
                                            • -t or --type - a type of the OSCAL object (can be either catalog, profile, component-definition, system-security-plan, etc)
                                            • -n or --name - a name of the OSCAL object

                                            Running trestle version -n nist -t catalog will return:

                                            Version of OSCAL object of nist catalog is: 1.0.0

                                            "},{"location":"cli/#trestle-init","title":"trestle init","text":"

                                            This command will create (initialize) a trestle workspace in the current directory with the necessary directory structure and trestle artefacts. This command has multiple modes that it can run in:

                                            • --full
                                            • --local
                                            • --govdocs

                                            By default trestle init will run in the --full mode.

                                            --full mode is meant to be used when full functionality of Trestle is used i.e. managing OSCAL models locally, govern documents or using Trestle for API purposes. dist repository will be used when trestle assemble command is used. Running trestle init --full will create the directory structure below for different artefacts:

                                            .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 dist\n\u2502   \u251c\u2500\u2500 catalogs\n\u2502   \u251c\u2500\u2500 profiles\n\u2502   \u251c\u2500\u2500 component-definitions\n\u2502   \u251c\u2500\u2500 system-security-plans\n\u2502   \u251c\u2500\u2500 assessment-plans\n\u2502   \u251c\u2500\u2500 assessment-results\n\u2502   \u2514\u2500\u2500 plan-of-action-and-milestones\n\u251c\u2500\u2500 catalogs\n\u251c\u2500\u2500 profiles\n\u251c\u2500\u2500 component-definitions\n\u251c\u2500\u2500 system-security-plans\n\u251c\u2500\u2500 assessment-plans\n\u251c\u2500\u2500 assessment-results\n\u2514\u2500\u2500 plan-of-action-and-milestones\n

                                            --local mode is meant to be used when Trestle is used to only manage OSCAL models locally. Running trestle init --local will create the directory structure below for different artefacts:

                                            .\n\u251c\u2500\u2500 .trestle\n\u251c\u2500\u2500 catalogs\n\u251c\u2500\u2500 profiles\n\u251c\u2500\u2500 component-definitions\n\u251c\u2500\u2500 system-security-plans\n\u251c\u2500\u2500 assessment-plans\n\u251c\u2500\u2500 assessment-results\n\u2514\u2500\u2500 plan-of-action-and-milestones\n

                                            --govdocs mode is meant to be used when Trestle is only used to govern documents. Running trestle init --govdocs will create the directory structure below:

                                            .\n\u251c\u2500\u2500 .trestle\n

                                            .trestle directory is a special directory containing various trestle artefacts to help run various other commands.

                                            dist directory will contain the merged or assembled version of the top level models located on the source model directories which are: catalogs, profiles, component-definitions, system-security-plans, assessment-plans, assessment-results and plan-of-action-and-milestones.

                                            Notice that trestle is a highly opinionated tool and, therefore, the names of the files and directories that are created by any of the trestle commands and subcommands MUST NOT be changed manually.

                                            "},{"location":"cli/#trestle-create","title":"trestle create","text":"

                                            This command will create a bare-bones sample file for one of the top level OSCAL models, and it can also create new elements within an existing file. For example, trestle create -t catalog -o nist800-53 will create a sample catalog file, catalog.json in the catalog subdirectory, nist800-53 as shown below:

                                            .\n\u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 nist800-53\n        \u2514\u2500\u2500 catalog.json\n...\n

                                            The -t specifies the type of the model to create, which can be one of catalog, profile, component-definition, system-security-plan, assessment-plan, assessment-results, plan-of-action-and-milestones. Each type will be created in its corresponding directory, such as catalogs, profiles, etc.

                                            The following additional options are supported:

                                            • -o or --output: specifies the name/alias of a model. It is used as the prefix for the output filename under the dist directory and for naming the source subdirectories under catalogs, profiles, component-definitions, system-security-plans, assessment-plans, assessment-results or plan-of-action-and-milestones.

                                            The user can edit the parts of the generated OSCAL model by modifying the sample content in those directories.

                                            Passing -iof or --include-optional-fields will make trestle create generate a richer model containing all optional fields until finding recursion in the model (e.g controls within control).

                                            In addition, trestle create can create new components within an existing file by specifying the existing file name and the corresponding element path to create within that file.

                                            For example,

                                            $TRESTLE_BASEDIR/catalogs/nist800-53$ trestle create -f ./catalog.json -e catalog.metadata.roles

                                            will add the following property under the metadata property for a catalog that will be written to the appropriate file under catalogs/nist800-53 directory:

                                            {\n\"roles\": [\n{\n\"id\": \"REPLACE_ME\",\n\"title\": \"REPLACE_ME\"\n}\n]\n}\n

                                            Default values for mandatory datatypes will be like below. All UUID's will be populated by default whether or not they are mandatory.

                                              - DateTime: <Current date-time>\n- Boolean: false\n- Integer: 0\n- String: REPLACE_ME\n- Float/Double: 0.00\n- Id field: Auto generated UUID\n

                                            Again, passing -iof or --include-optional-fields will make trestle create generate a richer version of the element being created, by including optional fields.

                                            "},{"location":"cli/#trestle-import","title":"trestle import","text":"

                                            This command allows users to import existing OSCAL files so that they can be managed using trestle. For example trestle import -f /local_dir/existing_catalog.json -o my_existing_catalog will import existing_catalog.json into a new folder under catalogs as shown below:

                                            .\n\u251c\u2500\u2500 .trestle\n\u2514\u2500\u2500 catalogs\n    \u2514\u2500\u2500 my_existing_catalog\n        \u2514\u2500\u2500 catalog.json\n...\n

                                            The following options are supported:

                                            • -f or --file: specifies the path of an existing OSCAL file or URL to a remote file.
                                            • -o or --output: specifies the name/alias of a model. It is used as the prefix for the output filename under the dist directory and for naming the source subdirectories under catalogs, profiles, component-definitions, system-security-plans, assessment-plans, assessment-results or plan-of-action-and-milestones.

                                            The --file option may be an absolute or relative path, and it may be a URL. For details on allowed formats please see the documentation for the href command. The file must be imported from outside the current trestle directory or an error will result.

                                            The import subcommand can determine the type of the model that is to be imported by the contents of the file. But the file name must end with an allowed json or yaml extension: .json, .yaml, .yml

                                            During the import process the file must pass the validate test described below for the command, validate. If the file does not pass validation a warning will be given describing the nature of the problem and the import will fail.

                                            Once a file has been imported it can be split into a rich tree of sub-components as shown at the top of this document. But the file must be imported first.

                                            "},{"location":"cli/#trestle-replicate","title":"trestle replicate","text":"

                                            This command allows users to replicate a certain OSCAL model (file and directory structure). For example trestle replicate catalog -n cat1 -o cat11 will replicate the Catalog cat1 into cat11 directory. It can also regenerate all the UUIDs as required.

                                            "},{"location":"cli/#trestle-split","title":"trestle split","text":"

                                            This command allows users to further decompose a trestle model into additional subcomponents.

                                            The following options are currently supported:

                                            • -f or --file: this is optional and specifies the file path of the json/yaml file containing the elements that will be split.
                                            • -e or --elements: specifies the model subcomponent element(s) (JSON/YAML property path) that is/are going to be split. Multiple elements can be specified at once using a comma-separated value, e.g -e 'catalog.metadata,catalog.groups'. Make sure to include the quotes that enclose the comma-separated paths.

                                            If the element is of JSON/YAML type array list and you want trestle to create a separate subcomponent file per array item, the element needs to be suffixed with .*, e.g. -e 'catalog.groups.*'. If the suffix is not specified, split will place all array items in only one separate subcomponent file, e.g. 'groups.json'. Again, make sure to include the quotes around the elements.

                                            If you just want to split a file into all its constituent parts and the file does not contain a simple list of objects, you can still use * and the file will be split into all its non-trivial elements. Thus if you split a catalog with -e catalog.* the result will be a new directory, catalog, containing files representing the large items, back-matter.json, groups.json and metadata.json, but there will still be a catalog.json file containing just the catalog's uuid. Small items such as strings and dates cannot be split off and will remain in the original model file that is being split.

                                            Here are some examples. Starting with a single catalog file, my_catalog/catalog.json, if you do trestle split -f catalog.json -e 'catalog.*' you end up with:

                                            catalogs\n \u2517 my_catalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                            If you then split roles out of metadata as a single file containing a list of roles, trestle split -f catalog/metadata.json -e 'metadata.roles' you would end up with:

                                            catalogs\n \u2517 my_catalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2517 roles.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                            If instead you had specified -e 'metadata.roles.*' you would get:

                                            my_catalog\n \u2523 catalog\n \u2503 \u2523 metadata\n \u2503 \u2503 \u2517 roles\n \u2503 \u2503 \u2503 \u2523 00000__role.json\n \u2503 \u2503 \u2503 \u2517 00001__role.json\n \u2503 \u2523 back-matter.json\n \u2503 \u2523 groups.json\n \u2503 \u2517 metadata.json\n \u2517 catalog.json\n

                                            You can see there is no roles.json file anymore and instead there is a subdirectory, roles containing a list of files, one for each role.

                                            If the -f or --file option is not specified, the file to split will be determined from the elements specified, in the context of the current working directory. The current directory must be within a specific model (e.g. catalog or profile), and the element paths must either be absolute (e.g. catalog.metadata.roles) or relative to the current working directory. For example, if you are in catalogs/mycat/catalog/groups and you want to split the file 00000__group.json, you must use -f to specify the filename, and the element path can either be absolute, as catalog.group.*, or you can set the current working directory to where the file is and use element path group.*. This makes it easier to specify splits when deep in a directory structure.

                                            Every subdirectory in a trestle directory model should have a corresponding .json or .yaml file with the same name, except when that subdirectory corresponds to a list of items, such as catalog.groups. When those subcomponents are split/expanded each file or subdirectory under them represents an item of the collection. Because of that, if a corresponding groups.json | groups.yaml file were to exist, its contents would just be an empty representation of that collection and the user would need to be careful never to edit that file. Therefore, we decided not to create that corresponding file in those cases. Following the same logic, another exception is when all the fields from a .json | .yaml file are split, leaving the original file as an empty object. In that case, the file would be deleted as well.

                                            To inspect a file to see what elements can be split from it, use the describe command described below. It is also useful for inspection of files created by the split operation.

                                            "},{"location":"cli/#trestle-merge","title":"trestle merge","text":"

                                            The trestle merge command is the reversal of trestle split. This command allows users to reverse the decomposition of a trestle model by aggregating subcomponents scattered across multiple files or directories into the parent JSON/YAML file. To merge a model, you have to first change working directory to the root model component directory that you want to merge a sub-component model into. The following option is required:

                                            • -e or --elements: specifies the properties (JSON/YAML path) that will be merged, relative to the current working directory. This must contain at least 2 elements, where the last element is the model/sub-component to be merged into the second from last component.

                                            For example, in the command trestle merge -e 'catalog.metadata', executed in the same directory where catalog.json or the split catalog directory exists, the property metadata from metadata.json would be moved/merged into catalog.json. If the metadata model has already been split into smaller sub-component models previously, those smaller sub-components are first recusively merged into metadata, before merging metadata subcomponent into catalog. To specify merging every sub-component split from a component, .* can be used. For example, trestle merge -e 'catalog.*' command, issued from the directory where catalog.json orcatalog directory exists, will merge every single sub-component of that catalog back into the catalog.json.

                                            "},{"location":"cli/#trestle-describe","title":"trestle describe","text":"

                                            This command lets users inspect model files to explore contents using an optional element path. The command can work well in concert with split to show what each file contains, and probe within the contents to determine sub-components that can be extracted as separate files.

                                            Unlike split, describe only describes the contents of a single item, so the element path may not contain wildcards (*) or commas.

                                            For example, if a catalog file has been imported to catalogs/my_catalog/catalog.json then the commmand, trestle describe -f catalog.json might yield:

                                            #Model file catalog.json is of type catalog.Catalog and contains\nuuid: 613fca2d-704a-42e7-8e2b-b206fb92b456\nmetadata: common.Metadata\nparams: None\ncontrols: None\ngroups: list of 20 items of type catalog.Group\nback_matter: common.BackMatter\n

                                            Note that contents are listed even when they are empty (and therefore optional) so the full potential contents can be seen. Also note that if an item corresponds to a list of elements, the number and type of elements is provided. Finally, if an item is a simple string such as id, uuid or title, the string is shown directly up to a maximum of 100 characters. If the string is clipped it will be indicated by [truncated] at the end of the string.

                                            An element path can be specified to probe the contents, as in trestle describe -f catalog.json -e 'catalog.metadata.roles'. A possible response is:

                                            Model file catalog.json at element path catalog.metadata.roles is a list of 2 items of type common.Role\n

                                            You can also query individual elements, and elements of an element, e.g. trestle describe -f catalog.json -e 'catalog.groups.5.controls.3'

                                            # Model file catalog.json at element path catalog.groups.5.controls.3 is of type catalog.Control and contains:\nid: cp-4\nclass_: SP800-53\ntitle: Contingency Plan Testing\nparams: list of 2 items of type common.Parameter\nprops: list of 2 items of type common.Property\nlinks: list of 14 items of type common.Link\nparts: list of 2 items of type common.Part\ncontrols: list of 5 items of type catalog.Control\n

                                            (Note that the numbering starts at 0, so the .3 corresponds to the 4th element.)

                                            In all output from describe the type of the item shown corresponds to the python file and class of the corresponding OSCAL model in trestle.

                                            If you split items off a model so they end up in a subdirectory, the original file is referred to as a \"stripped\" model, with parts of it stripped off and only some elements remaining. For example, if you do trestle split -f catalog.json -e 'catalog.metadata' it will split off metadata from the original catalog.json file and place it in catalog/metadata.json. If you then do trestle describe -f catalog.json on the new file, it will say something like:

                                            # Model file catalog.json is of type stripped.Catalog and contains:\nuuid: 613fca2d-704a-42e7-8e2b-b206fb92b456\nparams: None\ncontrols: None\ngroups: list of 20 items of type catalog.Group\nback_matter: common.BackMatter\n

                                            Note that the type of the file is now stripped.Catalog and it no longer contains metadata. Even though metadata is no longer in the original .json file, trestle is still aware it is present in the model since it is properly placed as its own file in the subdirectory, catalog.

                                            "},{"location":"cli/#trestle-partial-object-validate","title":"trestle partial-object-validate","text":"

                                            OSCAL objects may be extremely large. Some systems may only be able to produce partial OSCAL objects. For example, the tanium-result-to-oscal-ar task produces the results attribute of an assessment-results object.

                                            trestle partial-object-validate allows the validation of any sub-element/attribute using element path.

                                            Using the example above trestle partial-object-validate -f results.json -e assessment-results.results.

                                            The file is not required to be in the trestle directory or required to be a specific file name.

                                            "},{"location":"cli/#example-valid-element-paths","title":"Example valid element-paths","text":"

                                            All element paths must be absolute e.g.: catalog.metadata catalog catalog.groups catalog.groups.group.controls.control.controls.control Remembering in the end you only care about the end type. So in this scenario catalog.groups.group.controls.control.controls.control is equivalent to catalog.controls.control.

                                            "},{"location":"cli/#trestle-href","title":"trestle href","text":"

                                            This command changes the href of an Import in a profile and is needed when generating an SSP (system security plan) with the author tool, ssp-generate. The Imports in a profile are used to load associated catalogs of controls and profiles, and must be available at the corresponding href uri. If an imported catalog is in the trestle directory then the href should be changed with a command of the form:

                                            trestle href -n my_profile -hr trestle://catalogs/my_catalog/catalog.json\n

                                            Similarly, if the item imported is a profile, a corresponding href should point to a json file in the profiles directory.

                                            Note that catalogs or profiles in the trestle directory are indicated by the trestle:// prefix, followed by the path from the top level models directory to the actual catalog file. The profile itself, which is having its imports modified, is just indicated by its name with the -n option.

                                            If the profile has more than one import, you can display the corresponding hrefs with:

                                            trestle href -n my_profile\n

                                            This will give a numbered list of the hrefs. You can then change them individually by providing the corresponding item number:

                                            trestle href -n my_profile -i 1 -hr trestle://catalogs/my_catalog/catalog.json\n

                                            This will change the href indexed as 1 when the list was displayed. The href's are indexed starting from 0.

                                            The trestle href command can also be used to change the value back to the intended one prior to distribution of the profile.

                                            The provided href can be of form trestle://, https://, sftp://, or file:///. If file:/// is used, the path provided must be absolute - and on Windows it must include the drive letter followed by a slash. The only time a relative path is allowed is with the trestle:// heading.

                                            A username and password may be embedded in the url for https://, and a CA certificate path will be searched from environment variables REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE in that order.

                                            Authorization for sftp:// access relies on the user's private key being either active via ssh-agent or supplied via the environment variable SSH_KEY. In the latter case it must not require a passphrase prompt.

                                            "},{"location":"cli/#trestle-assemble","title":"trestle assemble","text":"

                                            This command assembles all contents (files and directories) representing a specific model into a single OSCAL file located under dist folder. For example,

                                            $TRESTLE_BASEDIR$ trestle assemble catalog -n nist800-53

                                            will traverse the catalogs/nist800-53 directory and its children and combine all data into a OSCAL file that will be written to dist/catalogs/nist800-53.json. Note that the parts of catalog nist800-53 can be written in either YAML/JSON (e.g. based on the file extension), however, the output will be generated as YAML/JSON as desired. Trestle will infer the content type from the file extension and create the model representation appropriately in memory and then output in the desired format. Trestle assemble will also validate content as it assembles the files and make sure the contents are syntactically correct.

                                            "},{"location":"cli/#trestle-remove","title":"trestle remove","text":"

                                            The trestle remove command is the reversal of trestle create -f filename.json -e element_path, as it will remove the corresponding element from the specified file.

                                            "},{"location":"cli/#trestle-validate","title":"trestle validate","text":"

                                            Trestle validate checks the integrity of one or more OSCAL files in a number of ways.

                                            validate returns a non-zero return code if there is any validation problem detected in a file.

                                            The current list of validation modes that get checked internally are:

                                            Mode Purpose duplicates Detect whether disallowed duplicate uuid's are present oscal_version Confirm that the oscal version of the file is supported refs Confirm that all references in responsible parties are found in roles catalog Confirm all parameter ids in a catalog are unique links Confirm referenced resources are 1:1 with resources in backmatter

                                            You can validate a single model file by specifying its full path:

                                            trestle validate -f catalogs/my_cat/catalog.json

                                            or by specifying its model name and type:

                                            trestle validate -t catalog -n my_cat

                                            In addition to validating a single file you can validate all files of a given type with the -t option and no file name:

                                            trestle validate -t catalog

                                            And you can validate all models with the -a option:

                                            trestle validate -a

                                            Note that when you Import a file it will perform a full validation on it first, and if it does not pass validation the file cannot be imported.

                                            By default validate will display warning messages and a message indicating the file is valid, but you can suppress those messages with the -q --quiet option.

                                            The links validator is special because it always returns success that the file is valid - but it will list any inconsistencies it finds between the references to links, and corresponding links in the backmatter.

                                            "},{"location":"cli/#trestle-tasks","title":"trestle tasks","text":"

                                            Open Shift Compliance Operator and Tanium are supported as 3rd party tools.

                                            "},{"location":"cli/#trestle-task-xccdf-result-to-oscal-ar","title":"trestle task xccdf-result-to-oscal-ar","text":"

                                            The trestle task xccdf-result-to-oscal-ar command facilitates transformation of XCCDF results, e.g. OpenShift Compliance Operator (OSCO) scan results, .yaml files into OSCAL partial results .json files. Specify required config parameters to indicate the location of the input and the output. Specify optional config parameters to indicate the name of the oscal-metadata.yaml file, if any, and whether overwriting of existing output is permitted.

                                            Example command invocation:

                                            $TRESTLE_BASEDIR$ trestle task xccdf-result-to-oscal-ar -c /home/user/task.config

                                            Example config:

                                            /home/user/task.config

                                            [task.xccdf-result-to-oscal-ar]\n\ninput-dir =  /home/user/git/evidence/xccdf/input\noutput-dir = /home/user/git/evidence/oscal/output\noscal-metadata = oscal-metadata.yaml\noutput-overwrite = true\n

                                            input

                                            Example input directory contents listing:

                                            /home/user/git/evidence/xccdf/input

                                            -rw-rw-r--. 1 user user  3832 Feb  2 09:36 oscal-metadata.yaml\n-rw-rw-r--. 1 user user 49132 Feb  2 06:12 ssg-ocp4-ds-cis-111.222.333.444-pod.yaml\n-rw-rw-r--. 1 user user 52747 Feb  2 06:41 ssg-ocp4-ds-cis-111.222.333.555-pod.yaml\n

                                            Example input OSCO scan result file contents (snippet):

                                            ssg-ocp4-ds-cis-111.222.333.444-pod.yaml

                                            display sample
                                            apiVersion: v1\ndata:\nexit-code: '2'\nresults: |\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<TestResult xmlns=\"https://checklists.nist.gov/xccdf/1.2\" \nid=\"xccdf_org.open-scap_testresult_xccdf_org.ssgproject.content_profile_cis\"\nstart-time=\"2020-08-03T02:26:26+00:00\" end-time=\"2020-08-03T02:26:26+00:00\"\nversion=\"0.1.52\"\ntest-system=\"cpe:/a:redhat:openscap:1.3.3\">\n<benchmark href=\"/content/ssg-ocp4-ds.xml\" id=\"xccdf_org.ssgproject.content_benchmark_OCP-4\"/>\n<title>OSCAP Scan Result</title>\n<profile idref=\"xccdf_org.ssgproject.content_profile_cis\"/>\n<target>kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp</target>\n<target-facts>\n<fact name=\"urn:xccdf:fact:identifier\" type=\"string\">chroot:///host</fact>\n<fact name=\"urn:xccdf:fact:scanner:name\" type=\"string\">OpenSCAP</fact>\n<fact name=\"urn:xccdf:fact:scanner:version\" type=\"string\">1.3.3</fact>\n</target-facts>\n<target-id-ref system=\"https://scap.nist.gov/schema/asset-identification/1.1\" name=\"asset0\" href=\"\"/>\n<platform idref=\"cpe:/a:redhat:openshift_container_platform:4.1\"/>\n<platform idref=\"cpe:/a:machine\"/>\n<set-value idref=\"xccdf_org.ssgproject.content_value_ocp_data_root\">/kubernetes-api-resources</set-value>\n<set-value idref=\"xccdf_org.ssgproject.content_value_var_kube_authorization_mode\">Webhook</set-value>\n<set-value idref=\"xccdf_org.ssgproject.content_value_var_streaming_connection_timeouts\">5m</set-value>\n<rule-result idref=\"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\" time=\"2020-08-03T02:26:26+00:00\" severity=\"medium\" weight=\"1.000000\">\n<result>notselected</result>\n<ident system=\"https://nvd.nist.gov/cce/index.cfm\">CCE-84209-6</ident>\n</rule-result>\n<rule-result idref=\"xccdf_org.ssgproject.content_rule_accounts_restrict_service_account_tokens\" time=\"2020-08-03T02:26:26+00:00\" severity=\"medium\" weight=\"1.000000\">\n<result>notchecked</result>\n<message severity=\"info\">No candidate or applicable check found.</message>\n</rule-result>\n<rule-result idref=\"xccdf_org.ssgproject.content_rule_accounts_unique_service_account\" time=\"2020-08-03T02:26:26+00:00\" severity=\"medium\" weight=\"1.000000\">\n<result>notchecked</result>\n<message severity=\"info\">No candidate or applicable check found.</message>\n</rule-result>\n\n...\n\n</TestResult>\nkind: ConfigMap\nmetadata:\nannotations:\ncompliance-remediations/processed: ''\ncompliance.openshift.io/scan-error-msg: ''\ncompliance.openshift.io/scan-result: NON-COMPLIANT\nopenscap-scan-result/node: 111.222.333.444\ncreationTimestamp: '2020-08-03T02:26:34Z'\nlabels:\ncompliance-scan: ssg-ocp4-ds-cis\nname: ssg-ocp4-ds-cis-111.222.333.444-pod\nnamespace: openshift-compliance\nresourceVersion: '22693328'\nselfLink: /api/v1/namespaces/openshift-compliance/configmaps/ssg-ocp4-ds-cis-111.222.333.444-pod\nuid: 1da3ea81-0a25-4512-ad86-7ac360246b5d\n

                                            Example input OSCAL metadata file contents:

                                            oscal-metadata.yaml

                                            display sample
                                            ssg-ocp4-ds-cis-111.222.333.444-pod:\nlocker: https://github.mycorp.com/degenaro/evidence-locker\nnamespace: xccdf\nbenchmark: CIS Kubernetes Benchmark\nsubject-references:\ncomponent:\nuuid-ref: 56666738-0f9a-4e38-9aac-c0fad00a5821\ntype: component\ntitle: Red Hat OpenShift Kubernetes\ninventory-item:\nuuid-ref: 46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\ntype: inventory-item\ntitle: Pod\nproperties:\ntarget: kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\ntarget-ip: 111.222.333.444\ncluster-name: ROKS-OpenSCAP-1\ncluster-type: openshift\ncluster-region: us-south\n\nssg-rhel7-ds-cis-111.222.333.444-pod:\nlocker: https://github.mycorp.com/degenaro/evidence-locker\nnamespace: xccdf\nbenchmark: CIS Kubernetes Benchmark\nsubject-references:\ncomponent:\nuuid-ref: 89cfe7a7-ce6b-4699-aa7b-2f5739c72001\ntype: component\ntitle: RedHat Enterprise Linux 7.8\ninventory-item:\nuuid-ref: 46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\ntype: inventory-item\ntitle: VM\nproperties:\ntarget: kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\ntarget-ip: 111.222.333.444\ncluster-name: ROKS-OpenSCAP-1\ncluster-type: openshift\ncluster-region: us-south\n

                                            metadata format

                                            The oscal-metadata.yaml file comprises one or more mappings. Below is shown the format of a single mapping. The items in angle brackets are to be replaced with desired values for augmenting the produced OSCAL.

                                            The mapping whose name matches the [metadata][name] in the evidence for the corresponding embedded XML, if any, will be used for augmenting the produced OSCAL.

                                            name:\nlocker: <locker>\nnamespace: <namespace>\nbenchmark: <benchmark>\nsubject-references:\ncomponent:\nuuid-ref: <uuid-ref-component>\ntype: <component-type>\ntitle: <component-title>\ninventory-item:\nuuid-ref: <uuid-ref-inventory-item>\ntype: <inventory-item-type>\ntitle: <inventory-item-title>\nproperties:\ntarget: <target>\ncluster-name: <cluster-name>\ncluster-type: <cluster-type>\ncluster-region: <cluster-region>\n

                                            output

                                            Example output directory contents listing:

                                            /home/user/git/evidence/oscal/output

                                            -rw-rw-r--. 1 user user 49132 Feb  3 10:59 ssg-ocp4-ds-cis-111.222.333.444-pod.json\n-rw-rw-r--. 1 user user 52747 Feb  3 10:59 ssg-ocp4-ds-cis-111.222.333.555-pod.json\n

                                            Example output OSCAL Observations file contents (snippet):

                                            ssg-ocp4-ds-cis-111.222.333.444-pod.json

                                            display sample
                                            {\n\"observations\": [\n{\n\"uuid\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"title\": \"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\",\n\"description\": \"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://osco\",\n\"class\": \"source\",\n\"value\": \"CIS Kubernetes Benchmark\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"type\": \"component\",\n\"title\": \"Red Hat OpenShift Kubernetes\"\n},\n{\n\"uuid-ref\": \"46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\",\n\"type\": \"inventory-item\",\n\"title\": \"Pod\",\n\"props\": [\n{\n\"name\": \"target\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\"\n},\n{\n\"name\": \"target-ip\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"111.222.333.444\"\n},\n{\n\"name\": \"cluster-name\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"ROKS-OpenSCAP-1\"\n},\n{\n\"name\": \"cluster-type\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"openshift\"\n},\n{\n\"name\": \"cluster-region\",\n\"ns\": \"dns://osco\",\n\"class\": \"inventory-item\",\n\"value\": \"us-south\"\n}\n]\n}\n],\n\"relevant-evidence\": [\n{\n\"href\": \"https://github.mycorp.com/degenaro/evidence-locker\",\n\"description\": \"Evidence location.\",\n\"props\": [\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"id\",\n\"value\": \"xccdf_org.ssgproject.content_rule_ocp_idp_no_htpasswd\"\n},\n{\n\"name\": \"time\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"timestamp\",\n\"value\": \"2020-08-03T02:26:26+00:00\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"result\",\n\"value\": \"notselected\"\n}\n]\n}\n]\n}\n]\n}\n
                                            "},{"location":"cli/#trestle-task-tanium-result-to-oscal-ar","title":"trestle task tanium-result-to-oscal-ar","text":"

                                            The trestle task tanium-result-to-oscal-ar command facilitates transformation of Tanuim reports, each input file comprising individual lines consumable as json, into OSCAL partial results .json files. Specify required config parameters to indicate the location of the input and the output. Specify optional config parameter output-overwrite to indicate whether overwriting of existing output is permitted. Specify optional config parameter timestamp as ISO 8601 formated string (e.g., 2021-02-24T19:31:13+00:00) to override the timestamp attached to each Observation.

                                            Example command invocation:

                                            $TRESTLE_BASEDIR$ trestle task tanium-result-to-oscal-ar -c /home/user/task.config

                                            Example config:

                                            /home/user/task.config

                                            [task.tanium-result-to-oscal-ar]\n\ninput-dir =  /home/user/git/compliance/tanium/input\noutput-dir = /home/user/git/compliance/oscal/output\noutput-overwrite = true\n

                                            input

                                            Example input directory contents listing:

                                            /home/user/git/compliance/tanium/input

                                            -rw-rw-r--. 1 degenaro degenaro 1830 Mar  7 08:23 Tanium.comply-nist-results\n

                                            Tanium.comply-nist-results

                                            display sample
                                            {\n\"IP Address\": \"fe80::3cd5:564b:940e:49ab\",\n\"Computer Name\": \"cmp-wn-2106.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"Result\": \"pass\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
                                            {\n\"IP Address\": \"10.8.69.11\",\n\"Computer Name\": \"\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.2_L1_Ensure_Maximum_password_age_is_set_to_60_or_fewer_days_but_not_0\",\n\"Result\": \"pass\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
                                            {\n\"IP Address\": \"10.8.69.11\",\n\"Computer Name\": \"cmp-wn-2106.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.3_L1_Ensure_Minimum_password_age_is_set_to_1_or_more_days\",\n\"Result\": \"fail\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
                                            {\n\"IP Address\": \"10.8.69.11\",\n\"Computer Name\": \"cmp-wn-2106.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.4_L1_Ensure_Minimum_password_length_is_set_to_14_or_more_characters\",\n\"Result\": \"pass\",\n\"Custom ID\": \"800-53: IA-5\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n

                                            output

                                            Example output directory contents listing:

                                            /home/user/git/compliance/oscal/output

                                            -rw-rw-r--. 1 degenaro degenaro 6479 Mar  7 08:25 Tanium.oscal.json\n

                                            Tanium.oscal.json

                                            display sample
                                            {\n\"results\": [\n{\n\"uuid\": \"0ed0791e-5454-4d07-919f-15a0d806a5a8\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-04-13T00:16:20.000+00:00\",\n\"local-definitions\": {\n\"inventory-items\": [\n{\n\"uuid\": \"da8b87f6-2068-415f-94bb-e14e31b4f5c2\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"computer-name\",\n\"ns\": \"dns://tanium\",\n\"value\": \"cmp-wn-2106.demo.tanium.local\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"computer-ip\",\n\"ns\": \"dns://tanium\",\n\"value\": \"fe80::3cd5:564b:940e:49ab\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"value\": \"Windows 10\",\n\"class\": \" inventory-item\"\n}\n]\n},\n{\n\"uuid\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"computer-name\",\n\"ns\": \"dns://tanium\",\n\"value\": \"\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"computer-ip\",\n\"ns\": \"dns://tanium\",\n\"value\": \"10.8.69.11\",\n\"class\": \" inventory-item\"\n},\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"value\": \"Windows 10\",\n\"class\": \" inventory-item\"\n}\n]\n}\n]\n},\n\"reviewed-controls\": {\n\"control-selections\": [\n{}\n]\n},\n\"observations\": [\n{\n\"uuid\": \"b3250b66-fe6f-4ac0-be99-cb4ff093dc31\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"pass\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"da8b87f6-2068-415f-94bb-e14e31b4f5c2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n},\n{\n\"uuid\": \"5ae9c133-c32d-44c5-b52e-5af4513cb94a\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.2_L1_Ensure_Maximum_password_age_is_set_to_60_or_fewer_days_but_not_0\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.2_L1_Ensure_Maximum_password_age_is_set_to_60_or_fewer_days_but_not_0\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"pass\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n},\n{\n\"uuid\": \"8d021edc-176e-4373-a3c4-a19e954c1e4d\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.3_L1_Ensure_Minimum_password_age_is_set_to_1_or_more_days\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.3_L1_Ensure_Minimum_password_age_is_set_to_1_or_more_days\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"fail\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n},\n{\n\"uuid\": \"36aa7551-d047-4f4a-9853-6ac63cfc9e48\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.4_L1_Ensure_Minimum_password_length_is_set_to_14_or_more_characters\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"class\": \"source\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.4_L1_Ensure_Minimum_password_length_is_set_to_14_or_more_characters\",\n\"class\": \"id\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"pass\",\n\"class\": \"result\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"f3ab87b2-70c1-4332-991e-c003d4314c0b\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-04-13T00:16:20.000+00:00\"\n}\n],\n\"findings\": [\n{\n\"uuid\": \"ba4e264f-0aee-4ead-9ee3-6161c5cc4ecb\",\n\"title\": \"800-53: IA-5\",\n\"description\": \"800-53: IA-5\",\n\"target\": {\n\"type\": \"objective-id\",\n\"id-ref\": \"800-53: IA-5\",\n\"props\": [\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"value\": \"NIST 800-53\",\n\"class\": \"source\"\n},\n{\n\"name\": \"id-ref\",\n\"ns\": \"dns://tanium\",\n\"value\": \"800-53: IA-5\",\n\"class\": \"source\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"value\": \"FAIL\",\n\"class\": \"STRVALUE\"\n}\n],\n\"status\": \"not-satisfied\"\n},\n\"related-observations\": [\n{\n\"observation-uuid\": \"b3250b66-fe6f-4ac0-be99-cb4ff093dc31\"\n},\n{\n\"observation-uuid\": \"5ae9c133-c32d-44c5-b52e-5af4513cb94a\"\n},\n{\n\"observation-uuid\": \"8d021edc-176e-4373-a3c4-a19e954c1e4d\"\n},\n{\n\"observation-uuid\": \"36aa7551-d047-4f4a-9853-6ac63cfc9e48\"\n}\n]\n}\n]\n}\n]\n}\n
                                            "},{"location":"cli/#trestle-task-xlsx-to-oscal-cd","title":"trestle task xlsx-to-oscal-cd","text":"

                                            The trestle task xlsx-to-oscal-cd command facilitates transformation of an excel spreadsheet into an OSCAL component-definition.json file. Specify in the config:

                                            • location of catalog file
                                            • location of spreadsheet file
                                            • work sheet name in the spreadsheet file
                                            • output directory to write the component-definition.json file
                                            • whether or not to overwrite an existing component-definition.json file
                                            • the organization name
                                            • the organization remarks
                                            • the namespace
                                            • comma separated mappings from name to class
                                            • the catalog URL
                                            • the catalog title

                                              Example command invocation:

                                              $TRESTLE_BASEDIR$ trestle task xlsx-to-oscal-cd -c /home/user/task-xlsx-to-oscal-cd.config

                                              Example config:

                                              /home/user/task-xlsx-to-oscal-cd.config

                                              [task.xlsx-to-oscal-cd]\n\ncatalog-file = nist-content/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json\nspread-sheet-file = /home/user/compliance/data/spread-sheet/good.xlsx\nwork-sheet-name = example_best_practices_controls\noutput-dir = /home/user/compliance/data/tasks/xlsx/output\noutput-overwrite = true\n\norg-name = International Business Machines\norg-remarks = IBM\nnamespace = https://oscal-compass.github.io/compliance-trestle/schemas/oscal/cd/ibm-cloud\nproperty-name-to-class = goal_name_id:scc_goal_name_id, goal_version:scc_goal_version\ncatalog-url = https://github.com/usnistgov/oscal-content/blob/master/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json\ncatalog-title = NIST Special Publication 800-53 Revision 4\n

                                              catalog-file

                                              Example catalog-file:

                                              nist-content/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json

                                              spread-sheet-file

                                              Example spread-sheet-file:

                                              /home/user/compliance/data/spread-sheet/good.xlsx

                                              output

                                              Example component-definition.json:

                                              /home/user/compliance/data/tasks/xlsx/output/component-definition.json

                                              "},{"location":"cli/#spreadsheet-to-component-definition-mapping","title":"spreadsheet to component definition mapping","text":"display mapping table spreadsheet column name component definition path comments ControlId
                                              • implemented_requirement.property[name='goal_name_id'].value
                                                • only used if column 'goal_name_id' is empty ControlText
                                                  • implemented_requirement.property[name='goal_name_id'].remarks
                                                    • transformation code replaces \"Check whether\" with \"Ensure\" in text Nist Mappings
                                                      • implemented_requirement.description
                                                        • heading may span multiple columns
                                                        • one value expected per column
                                                        • each entry is separated into control + statements (if any) ResourceTitle
                                                          • component.title
                                                          • component.description
                                                          • component.control-implementation.description + {text}
                                                            goal_name_id
                                                            • implemented_requirement.property[name='goal_name_id'].value
                                                              Version
                                                              • implemented_requirement.property[name='goal_version'].value
                                                                • Value from spreadsheet is not currently used.
                                                                • Value '1.0' is hard coded. Parameter [optional parameter]
                                                                  • implemented_requirement.set_parameter.param_id
                                                                    • The expected text is in two parts separated by '\\n'.
                                                                    • The text following the '\\n' is the value used. Values [alternatives]
                                                                      • implemented_requirement.set_parameter.values
                                                                        • The expected text is of the following format:
                                                                        • v0, [v1, v2...]
                                                                        • The value v0 is used."},{"location":"cli/#trestle-task-xlsx-to-oscal-profile","title":"trestle task xlsx-to-oscal-profile","text":"

                                                                          The trestle task xlsx-to-oscal-profile command facilitates transformation of an excel spreadsheet into an OSCAL profile.json file. Specify in the config:

                                                                          • the href URL of the spreadsheet
                                                                          • file system location of spreadsheet file
                                                                          • work sheet name in the spreadsheet file
                                                                          • output directory to write the profile.json file
                                                                          • whether or not to overwrite an existing profile.json file
                                                                          • the profile title

                                                                            Example command invocation:

                                                                            $TRESTLE_BASEDIR$ trestle task xlsx-to-oscal-profile -c /home/user/task-xlsx-to-oscal-profile.config

                                                                            Example config:

                                                                            /home/user/task-xlsx-to-oscal-profile.config

                                                                            [task.xlsx-to-oscal-profile]\n\nspread-sheet-url = https://github.mycorp.com/spread-sheets/good.xlsx\nspread-sheet-file = /home/user/compliance/data/spread-sheet/good.xlsx\nwork-sheet-name = example_best_practices_controls\noutput-dir = /home/user/compliance/data/tasks/xlsx/output\noutput-overwrite = true\n\nprofile-title = IBM Best Practices SCC GOALS\n

                                                                            spread-sheet-file

                                                                            Example spread-sheet-file:

                                                                            /home/user/compliance/data/spread-sheet/good.xlsx

                                                                            output

                                                                            Example profile.json:

                                                                            /home/user/compliance/data/tasks/xlsx/output/profile.json

                                                                            "},{"location":"demonstrations-content/","title":"Trestle demonstration projects and content","text":"

                                                                            Trestle has a number of demonstrations setup in the oscal-compass/compliance-trestle-demos repository which is intended to be a single point of call for demonstrations and content.

                                                                            If you are interested in contributing a demonstration / content open a PR to the demonstration repo and a PR to this page.

                                                                            Demonstrations, where practical, should include instructions on how they were created.

                                                                            "},{"location":"demonstrations-content/#current-demonstrations","title":"Current demonstrations","text":""},{"location":"demonstrations-content/#simple-sdk-examples","title":"Simple sdk examples.","text":"

                                                                            This folder contains a number of small examples for using the trestle OSCAL sdks.

                                                                            "},{"location":"demonstrations-content/#arc42-architectural-template-enforcement-using-trestle-author","title":"arc42 architectural template enforcement using trestle author.","text":"

                                                                            arc42 have created a set of open-source architecture documentation templates. This demonstration uses trestle author to enforce use of the (modified) arc42 templates.

                                                                            "},{"location":"demonstrations-content/#trestle-flask-microservice-demonstration","title":"Trestle flask microservice demonstration.","text":"

                                                                            trestle uses a python library called pydantic to form the underlying OSCAL object models. flask-pydantic introduces a mechanism which integrates pydantic models into flask, providing automated user input validation in one line of code. This demo accepts a catalog as a POSTed object, throwing errors if the catalog does not meet the schema, and returns the catalog in the response. Find the demonstration here.

                                                                            "},{"location":"demonstrations-content/#creating-a-cis-controls-catalog-from-an-excel-spreadsheet","title":"Creating a CIS controls catalog from an excel spreadsheet.","text":"

                                                                            The Centre for Internet Security (CIS) produce a number of cross industry standards for IT security including their platform specific benchmarks and a suite of controls. This demo converts a spreadsheet of those controls into a a catalog and three profiles.

                                                                            "},{"location":"demonstrations-content/#creating-an-ssp-using-trestle-author","title":"Creating an SSP using trestle author.","text":"

                                                                            trestle author ssp-generate and trestle author ssp-assemble allow users to generate first a set of markdown documents to allow easy editing of control responses and second to reassemble that information up into an OSCAL ssp document. This is a 'baseline' demonstration with more sophisticated updates expected in the near term.

                                                                            "},{"location":"demonstrations-content/#trestle-repository-api-trestlecorerepository","title":"Trestle Repository API (trestle.core.repository)","text":"

                                                                            trestle.core.repository is an API which abstracts users from the file system of a trestle repository. It provides a way for external developers to access a trestle repository without relying on presumptions (such as cwd being within the repository). Find the demo here.

                                                                            "},{"location":"demonstrations-content/#task-examples","title":"Task examples","text":""},{"location":"demonstrations-content/#convert-a-spreadsheet-into-a-component-definition","title":"Convert a spreadsheet into a component-definition","text":"

                                                                            This demonstration shows how to use the trestle task xlsx-to-oscal-cd functionality.

                                                                            "},{"location":"demonstrations-content/#convert-a-xccdf-result-into-a-partial-assessment-results","title":"Convert a xccdf result into a partial assessment-results","text":"

                                                                            This demonstration shows how to use the trestle task xccdf_result_to_oscal_ar functionality.

                                                                            "},{"location":"errors/","title":"Known errors and limitations","text":""},{"location":"errors/#utf-8-encoding-only","title":"utf-8 encoding only","text":"

                                                                            Trestle supports only utf8 as a file text-encoding. If non-utf8 files are encountered, errors will be reported / thrown. Trestle provides a script that may be used to convert files to utf8 in a destructive manner that may change the file contents.

                                                                            WARNING: This script is potentially destructive and may remove / damage content. Ensure you have a backup before use.

                                                                            "},{"location":"license/","title":"License","text":"
                                                                                                             Apache License\n                           Version 2.0, January 2004\n                        https://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n
                                                                            "},{"location":"maintainers/","title":"Maintainers","text":"

                                                                            Trestle was designed and open sourced by a team based at IBM Research and others around the world. The list includes:

                                                                            Alejandro Jose Leiva Palomo AleJo2995

                                                                            Christopher Butler butler54

                                                                            Lou Degenaro degenaro

                                                                            Jennifer Power jpower432

                                                                            Manjiree Gadgil mrgadgil

                                                                            Vikas Agarwal vikas-agarwal76

                                                                            "},{"location":"mkdocs_code_of_conduct/","title":"Code of Conduct","text":"

                                                                            Please refer to our OSCAL Compass Community Code of Conduct.

                                                                            "},{"location":"python_trestle_setup/","title":"Install trestle in a python virtual environment","text":"

                                                                            There are a few things you need to to start using trestle:

                                                                            • Make sure you have a working and recent Python environment
                                                                            • Set up a Python virtual environment
                                                                            • Download and install trestle
                                                                            • Confirm it is working properly
                                                                            • Create a trestle workspace
                                                                            "},{"location":"python_trestle_setup/#confirm-you-have-python-installed","title":"Confirm you have python installed","text":"
                                                                            • Ensure you have a modern Python (3.9, 3.10, 3.11).
                                                                            $ python -V\nPython 3.9.2\n
                                                                            "},{"location":"python_trestle_setup/#setup-a-virtual-environment","title":"Setup a virtual environment","text":"

                                                                            There are many ways to do this on Windows, Mac and Linux and with different Python installations, so please consult the documentation associated with your platform. Below is how it works on a typical Linux platform.

                                                                            $ cd\n$ python -m venv venv.trestle\n$ source venv.trestle/bin/activate\n(venv.trestle)$\n
                                                                            • Ensure you have a modern pip (19.x or greater).
                                                                            (venv.trestle)$ python -m pip --version\npip 19.2.3 from /home...\n

                                                                            You should probably upgrade your pip to the latest version with:

                                                                            (venv.trestle)$ python -m pip install --upgrade pip\n

                                                                            Details can be found at Installation - pip documentation

                                                                            "},{"location":"python_trestle_setup/#install-trestle","title":"Install trestle","text":"
                                                                            • Install compliance-trestle.
                                                                            (venv.trestle)$ python -m pip install compliance-trestle\nLooking in indexes: https://pypi.org/simple,...\n
                                                                            "},{"location":"python_trestle_setup/#confirm-trestle-is-installed-properly","title":"Confirm trestle is installed properly","text":"
                                                                            • Check trestle viability (and view help).
                                                                            (venv.trestle)$ trestle -h\nusage: trestle [-h]\n{assemble,author,create,describe,href,import,init,merge,partial-object-validate,remove,replicate,split,task,validate,version}\n...\n
                                                                            Full help text
                                                                            Manage OSCAL files in a human friendly manner.\n\npositional arguments:\n  {assemble,author,create,describe,href,import,init,merge,partial-object-validate,remove,replicate,split,task,validate,version}\nassemble            Assemble all subcomponents from a specified trestle model into a single JSON/YAML file under\n                        dist.\n    author              trestle author, a collection of commands for authoring compliance content outside of OSCAL.\n    create              Create a sample OSCAL model in trestle project or create new elements within a given model.\n    describe            Describe contents of a model file including optional element path.\n    href                Change href of import in profile to point to catalog in trestle project. This command is\n                        needed when generating an SSP with a profile that imports a catalog from a temporary location\n                        different from the final intended location of the catalog. Omit the href argument to see the\n                        list of current imports in the profile.\n    import              Import an existing full OSCAL model into the trestle project.\n    init                Initialize a trestle working directory.\n    merge               Merge subcomponents on a trestle model.\n    partial-object-validate\n                        Direct validation any oscal object in a file, including list objects.\n    remove              Remove a subcomponent to an existing model.\n    replicate           Replicate a top level model within the trestle directory structure.\n    split               Split subcomponents on a trestle model.\n    task                Run arbitrary trestle tasks in a simple and extensible methodology.\n    validate            Validate contents of a trestle model in different modes.\n    version             Output version info for trestle and OSCAL.\n\noptional arguments:\n  -h, --help            show this help message and exit\n
                                                                            "},{"location":"python_trestle_setup/#create-a-trestle-workspace","title":"Create a trestle workspace","text":"
                                                                            • Create trestle workspace.
                                                                            (venv.trestle)$ mkdir trestle.workspace\n(venv.trestle)$ cd trestle.workspace\n(venv.trestle)$ trestle init\nInitialized trestle project successfully in /home/<user>/trestle.workspace\n

                                                                            Congratulations! You now have a working trestle workspace for safe manipulation of OSCAL documents!

                                                                            "},{"location":"trestle_author/","title":"Trestle CLI for Governance of Authored Documents","text":"

                                                                            This document is organized in a multiple collapsable sections for ease of use. Start by reading the overview and setting up the Trestle workspace and then proceed to other sections, to learn more about Trestle authoring capabilities.

                                                                            "},{"location":"trestle_author/#contents","title":"Contents","text":"1. Overview 2. Setting up the Trestle workspace 3. Authoring of Documents Documents Structural Enforcement 4. Authoring of OSCAL Models"},{"location":"trestle_author/#overview","title":"Overview","text":"

                                                                            The premise of trestle is to support managing compliance artifacts as code. When this is considered, many organisations using {github|gitlab|bitbucket} rely on markdown documents for documentary artifacts that may either directly or indirectly support compliance efforts.

                                                                            To support this, trestle has the concept of 'governing' documents that are authored documents: Where structural conditions are enforced on the markdown documents to allow automation and to ensure business processes are met.

                                                                            Living in the GitOps world this capability is anchored with markdown files as the core of the workflows. Currently drawio files are also supported for a subset of enforcement mechanisms.

                                                                            Setting Up Templates and Documents Via CLI

                                                                            Trestle allows the setup of templates and governed documents in a several different ways based on the nature of the needed governance.

                                                                            Definitions used in this section:

                                                                            • document - a markdown or drawio file that needs to be validated against some template.
                                                                            • template - an individual markdown or drawio file containing metadata and/or headings against which the documents will be validated.
                                                                            • task - a name of the folders containing documents and their respective templates.
                                                                            • template folder - an individual folder containing the templates that documents needs to be validated against.

                                                                            You can set up multiple different tasks and types of validations in the same workspace.

                                                                            Setup Trestle for:

                                                                            docs - Validating documents against one specific template (one template per task) Template Versioning"},{"location":"trestle_author/#why-is-this-capability-in-trestle","title":"Why is this capability in trestle?","text":"

                                                                            While trestle provides editing support for OSCAL there is an unfortunate truth that for some compliance workflows:

                                                                            1. OSCAL does not cover the lower level operational workflows.
                                                                            2. Some users will not be comfortable editing in json/yaml/xml formats

                                                                            The markdown centric workflows allow transition path where capability is being developed

                                                                            "},{"location":"trestle_author/#setting-up-the-trestle-workspace","title":"Setting up the Trestle workspace","text":"

                                                                            To work with governed documents, you would need to initialize the Trestle workspace and create your first governed document and template.

                                                                            To create a trestle workspace that will contain all your templates and governed documents:

                                                                            mkdir my_workspace\ncd my_workspace\ntrestle init --govdocs\n>>> Initialized trestle project successfully in [user_path]/my_workspace\n

                                                                            The templates will be located in the /my_workspace/.trestle/author/. Please note that if you use MacOS or Linux distribution, by default .trestle will be hidden. You will need to reconfigure your system to show hidden folders if you want to see them listed.

                                                                            "},{"location":"trestle_author/#markdown-structural-enforcement","title":"Markdown structural enforcement","text":"

                                                                            Trestle templating enforces the documents to follow a specific structure. There are two ways in which structure is enforced in a document against template:

                                                                            1. Enforcing a YAML header (metadata) structure at the top of the markdown document.
                                                                            2. Enforcing a heading structure within the markdown document.

                                                                            Each document is validated against a specific template, see CLI section below on information on how to specify which template the document should be validated against.

                                                                            "},{"location":"trestle_author/#enforcing-yaml-header-metadata-structure","title":"Enforcing YAML header (metadata) structure","text":"

                                                                            Each template and document contains metadata in form of a YAML header that is placed on top. When the document is created (i.e. trestle docs setup) the metadata is copied from the template to the newly created document.

                                                                            Below is an example of a markdown file that contains YAML header:

                                                                            ---\ngroceries:\ngrocery1:\n  name: apple\n  type: fruit\n  bought-in: Local market\ngrocery2:\n  name: potato\n  type: vegetable\n  bought-in: Local market\ndate: 01-01-2022\nnot-important-field: not important\nx-trestle-version: 1.0.0\nx-trestle-ignore: not-important-field, bought-in\n---\n# The rest of my document\n

                                                                            Each field in the YAML header follows the key: value format. For YAML header we validate the structure and the presence of the \"keys\" and not the \"values\".

                                                                            The document YAML header(metadata) is said to be valid against the template, if and only if:

                                                                            1. It contains all keys from the template EXCEPT the keys that either:
                                                                            2. Start with x-trestle
                                                                            3. Are listed under the x-trestle-ignore key (i.e. x-trestle-ignore: not-important-field, bought-in)
                                                                            4. The version under x-trestle-template-version: key is matching the template.
                                                                            5. No new keys were added to the document.

                                                                            For example, this change to the YAML header above is acceptable:

                                                                            ---\ngroceries:\n  grocery1:\n      name: pear\n      type: fruit\n      bought-in: Superstore\n  grocery2:\n      name: potato\n      type: vegetable\n      bought-in: Local market\ndate: 10-10-2023\nnot-important-field: not important\nx-trestle-version: 1.0.0\nx-trestle-ignore: not-important-field, bought-in\n---\n# The rest of my document\n
                                                                            "},{"location":"trestle_author/#enforcing-heading-structure","title":"Enforcing heading structure","text":"

                                                                            Markdown headings are considered to be nested based on the heading level (i.e. number of #). For example, ## 1.1 Lower level heading is below # 1. top level heading.

                                                                            The document body is said to be valid against the template, if and only if,

                                                                            1. It contains all the headings provided in the template.
                                                                            2. No new headings were added at the top level (i.e. # New heading is not allowed).
                                                                            3. All original headings are in the same order as in the template.
                                                                            4. All headings must be in the hierarchical order (i.e. # Heading then ### Heading then ## Heading is invalid).
                                                                            5. If the --governed-heading option is provided, then document is valid if no keys has changed in the specified governed section.

                                                                            For example, consider this template as our starting point:

                                                                            # Template heading 1\nSome text\n# Template heading 2\n## Template sub heading\n

                                                                            Now we added new sections and ended up with the following document: (note: this document will be valid against the template above)

                                                                            # Template heading 1\nContent for heading one\n## Non-required sub header\nContent for non-required sub header\n# Template heading 2\nContent for heading two\n## Template sub heading\nContent for template sub heading\n### non required sub-sub heading\nThis sub-sub heading is okay\n

                                                                            However, violations such as adding or removing a heading at the top level are not acceptable:

                                                                            # Template heading 1\nContent for heading one\n## Non-required sub header\nContent for non-required sub header\n# Template heading 2\nContent for heading two\n## Template sub heading\nContent for template sub heading\n# Top level heading that is not okay <<< NOT OKAY\n

                                                                            For each of the headings - the text of the heading is enforced with one caveat:

                                                                            • If the template heading text is wrapped in curly brackets {} then the name is not measured e.g. # {Insert title here}.
                                                                            folders - Validating documents against multiple templates and ensuring folder structure (multiple individual templates per task) headers - Validate only the headers against a global or a specific template"},{"location":"trestle_author/#drawio-enforcement-mechanisms","title":"Drawio enforcement mechanisms","text":"

                                                                            Drawio or diagrams.net is a diagramming platform which has significant use for architecture diagrams. In the context of governance of content, trestle is supporting enforcement of metadata.

                                                                            Drawio (or mxgraph) files have a set of data fields. In a drawio file this is available in the edit menu as edit data. The diagram below shows how to access the (meta)data.

                                                                            The data presents as a set of key-value pairs which can be edited (see below). The data is bound to each tab in a drawio file. The trestle CLI currently expects that metadata (whether from the template or file to be measured) is in the first tab when editing the draw io file.

                                                                            "},{"location":"trestle_author/#validating-documents-against-one-specific-template","title":"Validating documents against one specific template","text":"

                                                                            In this section we describe the functionality of trestle author docs command.

                                                                            author docs is designed to support enforcing and generating templating markdown files within a single folder based on a task name. Currently author docs supports markdown files only.

                                                                            "},{"location":"trestle_author/#creating-new-tasktemplate","title":"Creating new task/template","text":"

                                                                            To create a new task with the necessary directory structures for running governed docs validation, run:

                                                                            trestle author docs setup -tn my_task_name

                                                                            This will create a template folder and a single template: TRESTLE_ROOT/.trestle/author/my_task_name/0.0.1/template.md. As well as an empty document folder: TRESTLE_ROOT/my_task_name/ The template will be applied to all markdown files in the task i.e.: TRESTLE_ROOT/my_task_name/*.md.

                                                                            "},{"location":"trestle_author/#extra-options","title":"Extra options","text":"
                                                                            • You can create different versions of the template by specifying the version via --template-version flag. See Template Versioning section for more information. By default if no version is provided 0.0.1 will be used.
                                                                            "},{"location":"trestle_author/#creating-new-document-for-the-task","title":"Creating new document for the task","text":"

                                                                            To create a new document that confirms to a template run:

                                                                            trestle author docs create-sample -tn my_task_name

                                                                            This will create a sample document in: TRESTLE_ROOT/my_task_name/my_task_name_000.md. Once created this document will be a complete copy of the template, however you can modify this file with your own content.

                                                                            "},{"location":"trestle_author/#extra-options_1","title":"Extra options","text":"
                                                                            • This command has no extra options
                                                                            "},{"location":"trestle_author/#validating-the-template","title":"Validating the template","text":"

                                                                            To ensure that the markdown in the template is parseable run:

                                                                            trestle author docs template-validate -tn my_task_name

                                                                            "},{"location":"trestle_author/#extra-options_2","title":"Extra options","text":"
                                                                            • If --governed-heading 'heading name' (-gh) is passed it ensures that the required heading exists.
                                                                            • If --header-validate (-hv) is passed the header will be validated as well.
                                                                            • If --header-only-validate (-hov) only the header and NOT the body will be validated
                                                                            "},{"location":"trestle_author/#validating-the-documents-against-the-template","title":"Validating the documents against the template","text":"

                                                                            To validate the documents against a template run:

                                                                            trestle author docs validate -tn my_task_name

                                                                            This will take the TRESTLE_ROOT/.trestle/author/my_task_name/template.md template and validate all markdown files here: TRESTLE_ROOT/my_task_name/*.md.

                                                                            Running the command will validate that markdown body in the document is valid against the template. Please note that by default the header will not be validated. See extra options for more validation options. To learn more on what exactly is validated please refer to Documents Structural Enforcement section in this document.

                                                                            "},{"location":"trestle_author/#extra-options_3","title":"Extra options","text":"
                                                                            • If --governed-heading (-gh) is passed it will ensure that the governed content was not modified. Governed content comes in the key: value format:
                                                                                 # Governed section\n     **Content Type:**  Foo\n     **Author(s):**  Bah\n     **Executive Owner:**  Stuff\n     **Technical Approver:**   John Doe (approved)\n     **Version:** 1.0.1\n

                                                                            Running trestle author docs validate -tn docs_task -gh=\"Governed section\" will ensure this content is present in the document.

                                                                            • If --ignore ^_.* (-ig) is passed it will validate all files except folders and files that start with underscore _. Use this option when you would like to ignore any folders or files that match given regular expression.
                                                                            • If --header-validate (-hv) is passed the header will be validated as well.
                                                                            • If --header-only-validate (-hov) is passed only the header and NOT the body will be validated.
                                                                            • If --readme-validate (-rv) is passed README.md will be validated as well, otherwise it is ignored.
                                                                            • If --recurse (-r) is passed the documents in the subfolders will also be validated. By default author docs only indexes a flat directory.
                                                                            • If --template-version 1.0.0 (-tv) is passed the header field x-trestle-template-version will be ignored and document will be forcefully validated against template of version 1.0.0. Use this for testing purposes only when you need to validate the document against a specific template. By default the template version will be determined based on x-trestle-template-version in the document.
                                                                            "},{"location":"trestle_author/#validating-the-documents-against-different-templates","title":"Validating the documents against different templates","text":"

                                                                            Validation against multiple templates can be done when there is a scenario where you have multiple templates that will have multiple instances. In this particular case you can have a 1:1 relationship between the template and the instance document you are creating out of it, so validation can be performed based on template type and version of that particular template defined in headers.

                                                                            For that to happen you will need to provide your template with the following parameter at the yaml header level, matching the type of template to be implemented so that the validation can occur:

                                                                            x-trestle-template-type: insert_template_type_here

                                                                            Please, take into consideration that for the validation to happen you will also need to provide each instance document in the task folder a field called x-trestle-template-type: insert_template_type_here in the yaml header matching with the template name.

                                                                            ---\nauthors: tmp\nowner: tmp\nvalid:\nfrom: null\nto: null\nx-trestle-template-type: insert_template_type_here\n---\n

                                                                            With that, you will be able to create more than 1 instance document per template and give the instance the desired name.

                                                                            For instance, let\u00b4s consider the next folder structure:

                                                                            trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_2\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 a_template.md\n\u2503 \u2503 \u2503 \u2503 \u2523 another_template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 arhitecture.drawio\n\u2503 \u2517 config.ini\n\ntrestle_root\n \u2523 .trestle\n \u2523 my_task_2\n \u2503 \u2523 sample_folder_0\n \u2503 \u2503 \u2523 a_template_1.md\n \u2503 \u2503 \u2523 a_template_2.md\n \u2503 \u2503 \u2523 arhitecture_1.drawio\n \u2503 \u2503 \u2517 another_template_123.md\n

                                                                            If you noticed, names are no longer needed to match with exact template names, and that\u00b4s because validation will run through x-trestle-template-type field defined at the instance header, not through the name.

                                                                            To validate the documents against their respective templates using x-trestle-template-type, run:

                                                                            trestle author docs validate -tn my_task_name -vtt

                                                                            Now, -vtt stands for validate template type. Validate template type option will provide you the ability to have more than 1 instance per template validated.

                                                                            "},{"location":"trestle_author/#validating-against-multiple-templates","title":"Validating against multiple templates","text":"

                                                                            In this section we describe the functionality of trestle author folders command.

                                                                            author folders is designed to allow the assembly of groups of templates where each folder contains unique content. This command will validate that both: structure (i.e. all template documents are present) and content is preserved in the folder. Trestle author folders supports validation of both markdown and drawio files. Note that headers / metadata must be specified in each applicable template.

                                                                            "},{"location":"trestle_author/#creating-new-task-folder","title":"Creating new task folder","text":"

                                                                            To create a new task folder run:

                                                                            trestle author folders setup -tn my_task_2

                                                                            This will create a template folder with the following structure:

                                                                            trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_2\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 a_template.md\n\u2503 \u2503 \u2503 \u2503 \u2523 another_template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 arhitecture.drawio\n\u2503 \u2517 config.ini\n

                                                                            Each task folder is required to meet template requirements for all: a_template.md, another_template.md, and template.drawio. The names, numbers, and nesting of folders is user specifiable, however, unlike docs the names must be carried over to each instances.

                                                                            "},{"location":"trestle_author/#extra-options_4","title":"Extra options","text":"
                                                                            • You can create different versions of the template by specifying the version via --template-version flag. See Template Versioning section for more information. By default if no version is provided 0.0.1 will be used.
                                                                            "},{"location":"trestle_author/#creating-new-documents-for-the-task","title":"Creating new documents for the task","text":"

                                                                            Following the similar structure of docs, measurement occurs in the my_task_2 where this structure is enforced for every directory.

                                                                            To create a new folder with documents for the task run:

                                                                            trestle author folders create-sample -tn my_task_2

                                                                            This will create a subfolder in the my_task_2 with the same content as in template folder. Running it twice will result in:

                                                                            trestle_root\n \u2523 .trestle\n \u2523 my_task_2\n \u2503 \u2523 sample_folder_0\n \u2503 \u2503 \u2523 a_template.md\n \u2503 \u2503 \u2523 arhitecture.drawio\n \u2503 \u2503 \u2517 another_template.md\n\n \u2503 \u2517 sample_folder_1\n \u2503 \u2503 \u2523 a_template.md\n \u2503 \u2503 \u2523 arhitecture.drawio\n \u2503 \u2503 \u2517 another_template.md\n
                                                                            "},{"location":"trestle_author/#extra-options_5","title":"Extra options","text":"
                                                                            • This command has no extra options
                                                                            "},{"location":"trestle_author/#validating-the-templates","title":"Validating the templates","text":"

                                                                            To validate the documents against the template run:

                                                                            trestle author folders template-validate -tn my_task_2

                                                                            This will ensure that the respective template files are parseable.

                                                                            "},{"location":"trestle_author/#extra-options_6","title":"Extra options","text":"
                                                                            • This command has no extra options
                                                                            "},{"location":"trestle_author/#validating-the-documents-against-templates","title":"Validating the documents against templates","text":"

                                                                            The validation in trestle author folder runs similarly as in docs but now each document will be validated against the template with the same name as in the template folder.

                                                                            To validate the documents against their respective templates, run:

                                                                            trestle author folders validate -tn my_task_name

                                                                            This will validate all files. Please note that all files from the template folder must be present in the individual document folders.

                                                                            "},{"location":"trestle_author/#extra-options_7","title":"Extra options","text":"
                                                                            • If --governed-heading (-gh) is passed it will ensure that the governed content was not modified. Governed content comes in the key: value format:
                                                                                 # Governed section\n   **Content Type:**  Foo\n   **Author(s):**  Bah\n   **Executive Owner:**  Stuff\n   **Technical Approver:**   John Doe (approved)\n   **Version:** 1.0.1\n

                                                                            Running trestle author docs validate -tn docs_task -gh=\"Governed section\" will ensure this content is present in the document.

                                                                            • If --ignore ^_.* (-ig) is passed it will validate all files except folders and files that start with underscore _. Use this option when you would like to ignore any folders or files that match given regular expression.
                                                                            • If --header-validate (-hv) is passed the header will be validated as well.
                                                                            • If --header-only-validate (-hov) is passed only the header and NOT the body will be validated.
                                                                            • If --readme-validate (-rv) is passed README.md will be validated as well, otherwise it is ignored.
                                                                            • If --recurse (-r) is passed the documents in the subfolders will also be validated. By default author docs only indexes a flat directory.
                                                                            • If --template-version 1.0.0 (-tv) is passed the header field x-trestle-template-version will be ignored and document will be forcefully validated against template of version 1.0.0. Use this for testing purposes only when you need to validate the document against a specific template. By default the template version will be determined based on x-trestle-template-version in the document.
                                                                            "},{"location":"trestle_author/#validating-the-documents-against-different-templates_1","title":"Validating the documents against different templates","text":"

                                                                            Validation against multiple templates as stated before can be done, but there is another scenario that you can leverage on trestle to have multiple documents in the task folder corresponding to a single template.

                                                                            For that to happen you will need to provide your template with the following parameter at the yaml header level, matching the type of template to be implemented so the validation can occur:

                                                                            x-trestle-template-type: insert_template_type_here

                                                                            Please, take into consideration that for the validation to happen you will also need to provide each instance document in the task folder a field called x-trestle-template-type: insert_template_type_here in the yaml header matching with the template name.

                                                                            ---\nauthors: tmp\nowner: tmp\nvalid:\nfrom: null\nto: null\nx-trestle-template-type: insert_template_type_here\n---\n

                                                                            With that, you will be able to create more than 1 instance document per template and give the instance the desired name.

                                                                            For instance, let\u00b4s consider the next folder structure:

                                                                            trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_2\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 a_template.md\n\u2503 \u2503 \u2503 \u2503 \u2523 another_template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 arhitecture.drawio\n\u2503 \u2517 config.ini\n\ntrestle_root\n \u2523 .trestle\n \u2523 my_task_2\n \u2503 \u2523 sample_folder_0\n \u2503 \u2503 \u2523 a_template_1.md\n \u2503 \u2503 \u2523 a_template_2.md\n \u2503 \u2503 \u2523 arhitecture_1.drawio\n \u2503 \u2503 \u2517 another_template_123.md\n

                                                                            If you noticed, names are no longer needed to match with exact template names, and that\u00b4s because validation will run through x-trestle-template-type field defined at the instance header, not through the name.

                                                                            To validate the documents against their respective templates using x-trestle-template-type, run:

                                                                            trestle author folders validate -tn my_task_name -vtt

                                                                            Now, -vtt stands for validate template type. Validate template type option will provide you the ability to have more than 1 instance per template validated.

                                                                            "},{"location":"trestle_author/#validate-only-the-headers-against-a-global-or-a-specific-template","title":"Validate only the headers against a global or a specific template.","text":"

                                                                            In this section we describe the functionality of trestle author headers command.

                                                                            Trestle author headers supports a slightly different usecase than that of docs and folders above as only the YAML headers will be validated. This command can be useful when one does not care about the markdown structure and might want to use global templates (templates that are shared across multiple tasks).

                                                                            With headers template folder can contain both .md and .drawio files and each file will be validated against the template that matches the extension. Also headers allow user to have global templates that can be shared across multiple tasks.

                                                                            "},{"location":"trestle_author/#creating-new-tasktemplate_1","title":"Creating new task/template","text":"

                                                                            To create a new task run:

                                                                            trestle author headers setup -tn my_task_3

                                                                            This will create a template folder with the following format:

                                                                            trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 my_task_3\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 template.drawio\n\u2503 \u2517 config.ini\n
                                                                            "},{"location":"trestle_author/#extra-options_8","title":"Extra options","text":"
                                                                            • If --global (-g) is passed then __global__ then it will create trestle_root/.trestle/author/__global__ folder. Use this when you would like to use same template for multiple tasks.
                                                                              trestle_root\n\u2523 .trestle\n\u2503 \u2523 author\n\u2503 \u2503 \u2523 __global__\n\u2503 \u2503 \u2503 \u2523 0.0.1\n\u2503 \u2503 \u2503 \u2503 \u2523 template.md\n\u2503 \u2503 \u2503 \u2503 \u2517 template.drawio\n\u2503 \u2517 config.ini\n
                                                                            • You can create different versions of the template by specifying the version via --template-version flag. See Template Versioning section for more information. By default if no version is provided 0.0.1 will be used.
                                                                            "},{"location":"trestle_author/#creating-new-documents","title":"Creating new documents","text":"

                                                                            As of now this command does not support the automatic creation of the sample documents.

                                                                            "},{"location":"trestle_author/#validating-the-templates_1","title":"Validating the templates","text":"

                                                                            To validate the documents against the template run:

                                                                            trestle author headers template-validate -tn my_task_3

                                                                            This will ensure that the respective template files are parseable.

                                                                            "},{"location":"trestle_author/#extra-options_9","title":"Extra options","text":"
                                                                            • This command has no extra options
                                                                            "},{"location":"trestle_author/#validating-the-documents","title":"Validating the documents","text":"

                                                                            To validate the documents against the template run:

                                                                            trestle author headers validate -tn my_task_3

                                                                            This will validate all files within the directory against the templates (of the matching task name) by matching the extensions. Please note that only headers will be validated. There is no option to validate the body.

                                                                            "},{"location":"trestle_author/#extra-options_10","title":"Extra options","text":"
                                                                            • If --global (-g) is passed it will create trestle_root/.trestle/author/__global__ folder. Use this when you would like to use same template for multiple tasks.
                                                                            • If --ignore ^_.* (-ig) is passed it will validate all files except folders and files that start with underscore _. Use this option when you would like to ignore any folders or files that match given regular expression.
                                                                            • If --readme-validate (-rv) is passed README.md will be validated as well, otherwise it is ignored.
                                                                            • If --recurse (-r) is passed the documents in the subfolders will also be validated. By default author docs only indexes a flat directory.
                                                                            • If --template-version 1.0.0 (-tv) is passed the header field x-trestle-template-version will be ignored and document will be forcefully validated against template of version 1.0.0. Use this for testing purposes only when you need to validate the document against a specific template. By default the template version will be determined based on x-trestle-template-version in the document.
                                                                            "},{"location":"trestle_author/#template-versioning","title":"Template versioning","text":""},{"location":"trestle_author/#prerequisite","title":"Prerequisite:","text":"

                                                                            This section assumes that you have an existing Trestle workspace initialized, with existing template and governed documents. Please follow steps in the section Setting up the Trestle Workspace if you don't have one.

                                                                            Trestle provides the capability to version the templates and the documents via x-trestle-template-version field in the header.

                                                                            Consider an example where we have a governed document called Decision 1 that we now need to update to contain a new header field approved-status and a new required heading Heading n at the end, as demonstrated in the Figure below:

                                                                            The intended workflow in this scenario is to:

                                                                            1.Create a new version of the decisions template:

                                                                            cd my_workspace \ntrestle author docs setup -tn decisions -tv 0.1.1\n>>> Set template version to 0.1.1.\n>>> Template file setup for task decisions at .trestle/author/decisions/0.1.1/template.md\n>>> Task directory is decisions\n

                                                                            Add the new required content to the newly created template. In our example simply copy-paste all content from the .trestle/author/decisions/0.1.0/template.md and add the newly required fields.

                                                                            2.Create a new instance of that template.

                                                                            trestle author docs create-sample -tn decisions -tv 0.1.1\n>>> Set template version to 0.1.1.\n

                                                                            This step will create a copy of the template of version 0.1.1.

                                                                            Now you will need to fill the documents with the updated information and new fields.

                                                                            3.(Optional) Delete the old document.

                                                                            Now that you have a new version of the document, you can delete the old one if you no longer need it. You can also keep it if you would like to maintain a history of updates.

                                                                            4.Run validation.

                                                                            After filling the contents to the new version of the template, you can run the validation to ensure that everything works as expected.

                                                                            trestle author docs validate -tn decisions\n>>> Instances will be validated against template version specified in their headers.\n>>> VALID: decisions/decision_000.md\n
                                                                            "},{"location":"trestle_author/#oscal-authoring","title":"OSCAL Authoring","text":""},{"location":"trestle_author/#catalog-authoring","title":"Catalog authoring","text":"

                                                                            CLI evocation:

                                                                            1. To generate markdowns for editing a catalog

                                                                            trestle author catalog-generate

                                                                            1. To assemble markdowns to a JSON catalog

                                                                            trestle author catalog-assemble

                                                                            The catalog author commands allow you to convert a control catalog to markdown and edit its control statement, then assemble markdown back into an OSCAL catalog with the modifications to the statement. Items in the statement may be edited or added. For more details on its usage please see the catalog authoring tutorial.

                                                                            "},{"location":"trestle_author/#profile-authoring","title":"Profile authoring","text":"

                                                                            CLI evocation:

                                                                            1. To generate markdowns for editing a profile

                                                                            trestle author profile-generate

                                                                            1. To assemble markdowns to a JSON profile

                                                                            trestle author profile-assemble

                                                                            The profile author commands allow you to edit additions made by a profile to its imported controls that end up in the final resolved profile catalog. Only the additions may be edited or added to the generated markdown control files - and those additions can then be assembled into a new version of the original profile, with those additions. For more details on its usage please see the profile authoring tutorial.

                                                                            "},{"location":"trestle_author/#profile-generation-with-inheritance","title":"Profile generation with inheritance","text":"

                                                                            CLI evocation:

                                                                            trestle author profile-inherit

                                                                            The profile-inherit sub-command takes a given parent profile and filters its imported controls based inherited controls from a given SSP.

                                                                            The leveraged SSP is evaluated based on whether provided and responsibility statements for all by-component fields are set for each applicable control, as well as the implementation status. All components must have exported provided statements, no exported responsibility statements, and an implementation status of implemented in order for a control to be filtered from the output profile (i.e. controls delta profile).

                                                                            As with the other related author commands, if an existing destination file already exists, it is not updated if no changes would be made.

                                                                            For more details on its usage please see the ssp-filter tutorial.

                                                                            "},{"location":"trestle_author/#ssp-authoring","title":"SSP authoring","text":"

                                                                            CLI evocation:

                                                                            1. To generate markdowns for editing SSP

                                                                            trestle author ssp-generate

                                                                            1. To assemble markdowns to a JSON SSP

                                                                            trestle author ssp-assemble

                                                                            The ssp-generate sub-command creates a partial SSP (System Security Plan) from a profile and optional yaml header file. ssp-assemble can then assemble the markdown files into a single json SSP file.

                                                                            For more details on its usage please see the ssp authoring tutorial.

                                                                            "},{"location":"trestle_author/#ssp-content-filtering","title":"SSP Content Filtering","text":"

                                                                            CLI evocation:

                                                                            trestle author ssp-filter

                                                                            The ssp-filter sub-command takes a given SSP and filters its contents based on a given profile, list of components, control implementation status and/or control origination.

                                                                            If filtering by profile, the SSP is assumed to contain a superset of controls needed by the profile, and the filter operation generates a new SSP with just the controls needed by that profile. If the profile references a control not in the SSP, the routine fails with an error.

                                                                            If filtering by components, a colon-delimited list of components should be provided, with This system as the default name for the overall required component for the entire system. Case and spaces are ignored in the component names, so the names could be specified as --components \"this system: my component\". The resulting, filtered ssp will have updated implemented requirements with filtered by_components on each requirement, and filtered by_components on each statement.

                                                                            If filtering by control implementation status, a comma-delimited list of implementation status values should be provided. These values must comply with the OSCAL SSP format references's allowed values, which are as follows: implemented, partial, planned, alternative, and not-applicable.

                                                                            If filtering by control origination, a comma-delimited list of control origination values should be provided. These values must comply with the OSCAL SSP format references's allowed values for the control origination property, which are as follows: system-specific, inherited, organization, customer-configured, and customer-provided.

                                                                            You may filter by a combination of a profile, list of component names, implementation statuses, and control origination values.

                                                                            As with the other related author commands, if an existing destination file already exists, it is not updated if no changes would be made.

                                                                            For more details on its usage please see the ssp-filter tutorial.

                                                                            "},{"location":"trestle_author_jinja/","title":"Trestle author jinja - output templating support for oscal documents.","text":"

                                                                            Unfortunately OSCAL documents are not yet universally accepted. Therefore to support various OSCAL and non-OSCAL compliance workflows trestle author jinja is designed to provide end users with the ability to use jinja to produce customized output. This complements the more structured commands trestle author catalog-{assemble|generate}, trestle author profile-{assemble|generate} and trestle author ssp-{assemble|generate} and allows arbitrary use of jinja.

                                                                            "},{"location":"trestle_author_jinja/#jinja-and-jinja-extensions-provided-by-trestle","title":"Jinja and jinja extensions provided by trestle.","text":"

                                                                            Jinja is a powerful templating engine that is both more flexible that pure 'Moustache' approaches, and not coupled to a particular web application server (as an example Django templates). Users are encouraged to review the template designer documentation for jinja as all core functionality is exposed.

                                                                            Trestle's implementation of the Jinja command works in the following way:

                                                                            1. The template search space, by default, is relative to the current working directory.
                                                                            2. Trestle can inject a lookup table, into the jinja variables to contain booleans / substitutions required by end users using Moustache style variable substitutions.
                                                                            3. Trestle can provide a number of interfaces to OSCAL objects, currently a resolved catalog and a SSP, into jinja.
                                                                            4. Trestle supports custom jinja tags for importing.
                                                                            5. The jinja templating is recursive, to ensure all jinja tags are resolved as appropriate.

                                                                            More details will be on each of these points below.

                                                                            "},{"location":"trestle_author_jinja/#cli-invocation","title":"CLI invocation","text":"

                                                                            Note the examples here use markdown, however, jinja can quite easily target xml or html if used w/o specific markdown content. trestle author jinja -i input_template.md.jinja -o output_file.md -ssp SSP_NAME -p PROFILE_NAME -lut lookup_table.yaml -elp lut.prefix

                                                                            • -i input file path, relative to cwd. Users are encouraged to use the file_name.target_extension.jinja best practice as it helps mitigate issues, however is not required.
                                                                            • -o final output path, relative to cwd.
                                                                            • -ssp (optional) ssp name (in the trestle project). When used the jinja template will have a ssp_md_writer variable exposed to use.
                                                                            • -p (optional) profile name (in the trestle project). When used the jinja template will have resolved_catalog and catalog_interface variables to use.
                                                                            • -lut (optional) loads yaml into a dictionary in python for which each (top level) variable is available in jinja.
                                                                            • -elp (optional) a period separated prefix for the variables in the lookup table. E.g. if the lut contained banana: yellow and the prefix was fruit.tropical using {{ fruit.tropical.banana }} would print out yellow in the jinja template.
                                                                            • -bf (optional) use to provide a custom formatting of the substituted parameters in the text with brackets or markup formatting. Use dot (.) to indicate where the parameter value will be written. E.g. -bf *.* to italicize all substituted parameters, -bf Prefix:. to add Prefix: to all parameters, and -bf [.] to put square brackets around the parameters.
                                                                            • -vap (optional) use to specify a --value-assigned-prefix in front of parameters that have values assigned by the profile. An example would include the organization doing the assignment, e.g. -vap \"ACME Assignment:\" This is identical to the behavior of profile-resolve.
                                                                            • -vnap (optional) use to specify a --value-not-assigned-prefix in front of parameters that do not have values assigned by the profile. An example would be -vap \"Assignment:\" This is identical to the behavior of profile-resolve.
                                                                            "},{"location":"trestle_author_jinja/#sample-jinja-templates","title":"Sample jinja templates","text":"

                                                                            Below is a sample jinja template for SSP.

                                                                            template Description Optional args required Simple SSP template Sample ssp jinja template which prints out all control responses and includes a front-matter section -ssp and -p for the ssp json and corresponding profile, respectively. Also requires a frontmatter.md file"},{"location":"trestle_author_jinja/#variable-availability-in-the-jinja-template","title":"Variable availability in the jinja template.","text":""},{"location":"trestle_author_jinja/#lut","title":"LUT","text":"

                                                                            The lookup table is primarily used for string substitution and to provide variables for basic logic operations in jinja e.g.

                                                                            The LUT:

                                                                            names:\nOSCAL: Open Security Compliance Assessment Language\ntrestle_pip: compliance-trestle\ntrestle_module: trestle\nvariables:\nmac_os: true\n

                                                                            The Jinja template:

                                                                            Install via pip install {{ names.trestle_pip }} and invoke at the python REPL by import {{ names.trestle_module }}\n\n{% if variables.mac_os %}\nUsers are recommended to use homebrew to install the latest python 3 and then install python within a venv.\n{% endif %}\n

                                                                            The output:

                                                                            Install via pip install compliance-trestle and invoke at the python REPL by import trestle\n\nUsers are recommended to use homebrew to install the latest python 3 and then install python within a venv.\n

                                                                            Users are free to use the LUT to inject more complex variables (arrays of data etc) to use at their own will using standard jinja templating.

                                                                            "},{"location":"trestle_author_jinja/#resolved-catalog-interface-profile","title":"Resolved catalog interface (profile)","text":"

                                                                            Passing -p exposes a catalog, resolved from the profile, at catalog and a trestle.core.catalog_interface.CatalogInterface at catalog_interface.

                                                                            This allows user to perform various task such as iterating ove reach group and printing the group title.

                                                                            {% for group in catalog_interface.get_all_groups_from_catalog() +%}\n## {{ group.title }} {{ group.class }} \\({{ group.id|upper }}\\)\n
                                                                            "},{"location":"trestle_author_jinja/#ssp-interface","title":"SSP interface.","text":"

                                                                            If -ssp is passed a variable within the jinja template called ssp_md_writer is made available which is an instance of trestle.core.ssp_io.SSPMarkdownWriter. -ssp requires that -p has also been set.

                                                                            This as allows users, as an example to print out a control response, as markdown

                                                                            #### What is the solution and how is it implemented?\n{{ ssp_md_writer.get_control_response('my_control_id', 3)}}\n
                                                                            "},{"location":"trestle_author_jinja/#custom-jinja-tags","title":"Custom Jinja tags.","text":"

                                                                            Trestle provides custom jinja tags for use specifically with markdown: mdsection_include and md_clean_include.

                                                                            md_clean_include is similar to the native {% include 'sub_template' %} that jinja provides except for the following:

                                                                            1. md_clean_include will look for yaml headers in the markdown content and exclude it from the template
                                                                            2. md_clean_include can be used with an optional keyword argument heading_level argument
                                                                            3. {% md_clean_include 'path_to_file.md' heading_level=2 %}
                                                                            4. The heading level argument adjusts to (based on the number of hashes) the most significant heading in the document, if headings exist.

                                                                            mdsection_include is similar to the native md_clean_include except that.:

                                                                            1. mdsection_include requires an second positional argument which is the title of a heading, from a markdown file, which you want the content from.

                                                                            2. E.g: {% mdsection_include 'test_markdown.md' '# Header we want' %}

                                                                            3. mdsection_include can be used with an optional keyword argument heading_level argument similar to md_clean_include

                                                                            4. {% mdsection_include 'test_markdown.md' '# Header we want' %}

                                                                            5. The heading level argument adjusts to (based on the number of hashes) the most significant heading in the chosen section, if headings exist.

                                                                            md_datestamp inserts a date stamp into the output. By default the date is in the format '%Y-%m-%d', e.g. '2021-12-28' and is followed by a double newline to prevent subsequent headings failing to parse correctly. E.g: {% md_datestamp %} results in a date in the format '2021-12-28' being inserted. md_datestamp can be used with the following optional keyword arguments:

                                                                            1. format where a python datetime strftime format string is provided to format the output. E.g. {% md_datestamp format='%B %d, %Y' %} results in December 28, 2021 being inserted.
                                                                            2. newline is a boolean to control the addition of a double newline after the inserted date string. For example {% md_datestamp newline=false %} inserts a date in the default format, without additional newlines.
                                                                            "},{"location":"trestle_author_jinja/#generate-controls-as-individual-markdown-pages","title":"Generate controls as individual markdown pages.","text":"

                                                                            Trestle's Jinja functionality allows its users to generate individual markdown pages for each control from a resolved profile catalog. Such functionality can be used later on to pack individual pages into docs of various formats.

                                                                            When --docs-profile or -dp flag is provided as part of the trestle author jinja command, the provided Jinja template will be used to generate a markdown page for each control in each group.

                                                                            For example, suppose we would like to generate the markdown page for each control that would contain Control Objective, Control Statement, Expected Evidence, Implementation Guidance and say Table of Parameters used for this control. To achieve that, we can create a simple Jinja template that would be used to generate each page:

                                                                            # Control Page\n\n{{ control_writer.write_control_with_sections(\n   control,\n   profile,\n   group_title, \n   ['statement', 'objective', 'expected_evidence', 'implementation_guidance', 'table_of_parameters'], \n   {\n      'statement':'Control Statement',\n      'objective':'Control Objective', \n      'expected_evidence':'Expected Evidence', \n      'implementation_guidance':'Implementation Guidance', \n      'table_of_parameters':'Control Parameters'\n   }\n   ) \n\n   | safe\n}}\n

                                                                            The template above, would call a control writer that would print the required sections (specified in the list) with the provided headers (specified in the dictionary).

                                                                            We can then generate individual markdown pages by executing: trestle author jinja -i profile_to_docs.md.jinja -o controls -p some_profile -dp

                                                                            This will create a folder named controls, that would contain a folder per each group and a markdown file per each control in that group. Each markdown file would be formatted using the Jinja template above.

                                                                            The generated markdown files can then be assembled to the docs of the desired format by adding an indexing page.

                                                                            "},{"location":"api_reference/trestle.cli/","title":"cli","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.cli/#trestle.cli","title":"trestle.cli","text":"

                                                                            Starting point for the Trestle CLI.

                                                                            "},{"location":"api_reference/trestle.cli/#trestle.cli.logger","title":"logger","text":""},{"location":"api_reference/trestle.cli/#trestle.cli-classes","title":"Classes","text":""},{"location":"api_reference/trestle.cli/#trestle.cli.Trestle","title":" Trestle (CommandBase) ","text":"

                                                                            Manage OSCAL files in a human friendly manner.

                                                                            Source code in trestle/cli.py
                                                                            class Trestle(CommandBase):\n\"\"\"Manage OSCAL files in a human friendly manner.\"\"\"\n\n    subcommands = [\n        AssembleCmd,\n        AuthorCmd,\n        CreateCmd,\n        DescribeCmd,\n        HrefCmd,\n        ImportCmd,\n        InitCmd,\n        MergeCmd,\n        PartialObjectValidate,\n        RemoveCmd,\n        ReplicateCmd,\n        SplitCmd,\n        TaskCmd,\n        ValidateCmd,\n        VersionCmd\n    ]\n\n    discovered_plugins = {\n        name: importlib.import_module(name)\n        for finder,\n        name,\n        ispkg in pkgutil.iter_modules()\n        if name.startswith('trestle_')\n    }\n\n    logger.debug(discovered_plugins)\n    # This block is uncovered as trestle cannot find plugins in it's unit tests - it is the base module.\n    for plugin, value in discovered_plugins.items():  # pragma: nocover\n        for _, module, _ in pkgutil.iter_modules([pathlib.Path(value.__path__[0], 'commands')]):\n            logger.debug(module)\n            command_module = importlib.import_module(f'{plugin}.commands.{module}')\n            clsmembers = inspect.getmembers(command_module, inspect.isclass)\n            logger.debug(clsmembers)\n            for _, cmd_cls in clsmembers:\n                # add commands (derived from CommandPlusDocs or CommandBase) to subcommands list\n                if issubclass(cmd_cls, CommandBase):\n                    # don't add CommandPlusDocs or CommandBase\n                    if cmd_cls is not CommandPlusDocs and cmd_cls is not CommandBase:\n                        subcommands.append(cmd_cls)\n                        logger.info(f'{cmd_cls} added to subcommands from plugin {plugin}')\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-v', '--verbose', help=const.DISPLAY_VERBOSE_OUTPUT, action='count', default=0)\n        self.add_argument(\n            '-tr', '--trestle-root', help='Path of trestle root dir', type=pathlib.Path, default=pathlib.Path.cwd()\n        )\n
                                                                            "},{"location":"api_reference/trestle.cli/#trestle.cli.Trestle.discovered_plugins","title":"discovered_plugins","text":""},{"location":"api_reference/trestle.cli/#trestle.cli.Trestle.subcommands","title":"subcommands","text":""},{"location":"api_reference/trestle.cli/#trestle.cli-functions","title":"Functions","text":""},{"location":"api_reference/trestle.cli/#trestle.cli.run","title":"run()","text":"

                                                                            Run the trestle cli.

                                                                            Source code in trestle/cli.py
                                                                            def run() -> None:\n\"\"\"Run the trestle cli.\"\"\"\n    log.set_global_logging_levels()\n    logger.debug('Main entry point.')\n\n    exit(Trestle().run())\n
                                                                            "},{"location":"api_reference/trestle.common.common_types/","title":"common_types","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types","title":"trestle.common.common_types","text":"

                                                                            Special types are defined here.

                                                                            "},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.FixedUuidModel","title":"FixedUuidModel","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.OBT","title":"OBT","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TG","title":"TG","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TG2","title":"TG2","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TopLevelOscalModel","title":"TopLevelOscalModel","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithByComps","title":"TypeWithByComps","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithParamId","title":"TypeWithParamId","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithParts","title":"TypeWithParts","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithProps","title":"TypeWithProps","text":""},{"location":"api_reference/trestle.common.common_types/#trestle.common.common_types.TypeWithSetParams","title":"TypeWithSetParams","text":""},{"location":"api_reference/trestle.common.const/","title":"const","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.const/#trestle.common.const","title":"trestle.common.const","text":"

                                                                            Core constants module containing all constants.

                                                                            "},{"location":"api_reference/trestle.common.const/#trestle.common.const-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ADDED_BY_CONTROL_OWNER","title":"ADDED_BY_CONTROL_OWNER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.AFTER_HASHES_REGEX","title":"AFTER_HASHES_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.AGGREGATES","title":"AGGREGATES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ALIAS_PATH_SEPARATOR","title":"ALIAS_PATH_SEPARATOR: str","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ALLOWED_EXTENSIONS_IN_DIRS","title":"ALLOWED_EXTENSIONS_IN_DIRS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ALT_IDENTIFIER","title":"ALT_IDENTIFIER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_DESC_ELEMENT","title":"ARG_DESC_ELEMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_DESC_FILE","title":"ARG_DESC_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_DESC_MODE","title":"ARG_DESC_MODE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_ELEMENT","title":"ARG_ELEMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_ELEMENT_SHORT","title":"ARG_ELEMENT_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_FILE","title":"ARG_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_FILE_SHORT","title":"ARG_FILE_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_MODE","title":"ARG_MODE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_MODE_SHORT","title":"ARG_MODE_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_VALIDATE","title":"ARG_VALIDATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ARG_VALIDATE_SHORT","title":"ARG_VALIDATE_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ASSESMENT_OBJECTIVE_PART","title":"ASSESMENT_OBJECTIVE_PART","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.BUG_REPORT","title":"BUG_REPORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CACHE_ABS_DIR","title":"CACHE_ABS_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CLOSE_COMMENT","title":"CLOSE_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.COMPONENT_VALUES","title":"COMPONENT_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.COMP_DEF_RULES_PARAM_VALS_TAG","title":"COMP_DEF_RULES_PARAM_VALS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.COMP_DEF_RULES_TAG","title":"COMP_DEF_RULES_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_HEADER","title":"CONTROL_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_IMPLEMENTATION","title":"CONTROL_IMPLEMENTATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_OBJECTIVE_HEADER","title":"CONTROL_OBJECTIVE_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_ORIGINATION","title":"CONTROL_ORIGINATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_REGEX","title":"CONTROL_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.CONTROL_STATEMENT_HEADER","title":"CONTROL_STATEMENT_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DAY_SECONDS","title":"DAY_SECONDS: int","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DISPLAY_NAME","title":"DISPLAY_NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DISPLAY_VERBOSE_OUTPUT","title":"DISPLAY_VERBOSE_OUTPUT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.DRAWIO_FILE_EXT","title":"DRAWIO_FILE_EXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.EDITABLE_CONTENT","title":"EDITABLE_CONTENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ELEMENT_WILDCARD","title":"ELEMENT_WILDCARD","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FIELDS_SET","title":"FIELDS_SET","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILE_DIGIT_PREFIX_LENGTH","title":"FILE_DIGIT_PREFIX_LENGTH","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILE_ENCODING","title":"FILE_ENCODING","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILE_URI","title":"FILE_URI","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILTER_BY_COMPONENTS","title":"FILTER_BY_COMPONENTS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILTER_BY_PROFILE","title":"FILTER_BY_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.FILTER_EXCLUDE_COMPONENTS","title":"FILTER_EXCLUDE_COMPONENTS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.GENERATE_RESOLVED_CATALOG","title":"GENERATE_RESOLVED_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.GUIDELINES","title":"GUIDELINES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HEADER_RULE_ID","title":"HEADER_RULE_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_ALLOWED_SECTIONS","title":"HELP_ALLOWED_SECTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_COMPDEFS","title":"HELP_COMPDEFS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_FO_OUTPUT","title":"HELP_FO_OUTPUT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_INCLUDE_ALL_PARTS","title":"HELP_INCLUDE_ALL_PARTS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_LEVERAGED","title":"HELP_LEVERAGED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_MARKDOWN_NAME","title":"HELP_MARKDOWN_NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_OVERWRITE_HEADER_VALUES","title":"HELP_OVERWRITE_HEADER_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_REGENERATE","title":"HELP_REGENERATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_REQUIRED_SECTIONS","title":"HELP_REQUIRED_SECTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_SECTIONS","title":"HELP_SECTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_SET_PARAMS","title":"HELP_SET_PARAMS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_VERSION","title":"HELP_VERSION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HELP_YAML_PATH","title":"HELP_YAML_PATH","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HOUR_SECONDS","title":"HOUR_SECONDS: int","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HREF","title":"HREF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.HTTPS_URI","title":"HTTPS_URI","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IDX_SEP","title":"IDX_SEP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_POINT","title":"IMPLEMENTATION_POINT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_POINT_EXTERNAL","title":"IMPLEMENTATION_POINT_EXTERNAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_STATUS","title":"IMPLEMENTATION_STATUS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_STATUS_HEADER","title":"IMPLEMENTATION_STATUS_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTATION_STATUS_REMARKS_HEADER","title":"IMPLEMENTATION_STATUS_REMARKS_HEADER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IMPLEMENTED_REQUIREMENT","title":"IMPLEMENTED_REQUIREMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INHERITANCE_VIEW_DIR","title":"INHERITANCE_VIEW_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INHERITED_UUID","title":"INHERITED_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_FULL_HELP","title":"INIT_FULL_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_FULL_LONG","title":"INIT_FULL_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_FULL_SHORT","title":"INIT_FULL_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_GOVDOCS_HELP","title":"INIT_GOVDOCS_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_GOVDOCS_LONG","title":"INIT_GOVDOCS_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_GOVDOCS_SHORT","title":"INIT_GOVDOCS_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_LOCAL_HELP","title":"INIT_LOCAL_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_LOCAL_LONG","title":"INIT_LOCAL_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.INIT_LOCAL_SHORT","title":"INIT_LOCAL_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IOF_HELP","title":"IOF_HELP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IOF_LONG","title":"IOF_LONG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.IOF_SHORT","title":"IOF_SHORT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ITEM","title":"ITEM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.LABEL","title":"LABEL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.LEVERAGED_SSP","title":"LEVERAGED_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.LEV_AUTH_UUID","title":"LEV_AUTH_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MARKDOWN_FILE_EXT","title":"MARKDOWN_FILE_EXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MARKDOWN_URL_REGEX","title":"MARKDOWN_URL_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MATCH_ALL_EXCEPT_LETTERS_UNDERSCORE_SPACE_REGEX","title":"MATCH_ALL_EXCEPT_LETTERS_UNDERSCORE_SPACE_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_A_PLAN","title":"MODEL_DIR_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_A_RESULT","title":"MODEL_DIR_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_CATALOG","title":"MODEL_DIR_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_COMPDEF","title":"MODEL_DIR_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_LIST","title":"MODEL_DIR_LIST","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_POAM","title":"MODEL_DIR_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_PROFILE","title":"MODEL_DIR_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_SSP","title":"MODEL_DIR_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_DIR_TO_MODEL_MODULE","title":"MODEL_DIR_TO_MODEL_MODULE","text":"

                                                                            Map of model type to oscal module.

                                                                            "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_A_PLAN","title":"MODEL_MODULE_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_A_RESULT","title":"MODEL_MODULE_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_CATALOG","title":"MODEL_MODULE_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_COMPDEF","title":"MODEL_MODULE_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_LIST","title":"MODEL_MODULE_LIST","text":"

                                                                            Map of plural form of a model type to the oscal module that contains the classes related to it.

                                                                            "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_POAM","title":"MODEL_MODULE_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_PROFILE","title":"MODEL_MODULE_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_SSP","title":"MODEL_MODULE_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_MODULE_TO_MODEL_TYPE","title":"MODEL_MODULE_TO_MODEL_TYPE","text":"

                                                                            Map of model type to model directory.

                                                                            "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_A_PLAN","title":"MODEL_TYPE_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_A_RESULT","title":"MODEL_TYPE_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_CATALOG","title":"MODEL_TYPE_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_COMPDEF","title":"MODEL_TYPE_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_LIST","title":"MODEL_TYPE_LIST","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_POAM","title":"MODEL_TYPE_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_PROFILE","title":"MODEL_TYPE_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_SSP","title":"MODEL_TYPE_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_TO_MODEL_DIR","title":"MODEL_TYPE_TO_MODEL_DIR","text":"

                                                                            Element path separator

                                                                            "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODEL_TYPE_TO_MODEL_MODULE","title":"MODEL_TYPE_TO_MODEL_MODULE","text":"

                                                                            Map of model module to model type.

                                                                            "},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_A_PLAN","title":"MODULE_NAME_A_PLAN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_A_RESULT","title":"MODULE_NAME_A_RESULT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_CATALOG","title":"MODULE_NAME_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_COMPDEF","title":"MODULE_NAME_COMPDEF","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_POAM","title":"MODULE_NAME_POAM","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_PROFILE","title":"MODULE_NAME_PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.MODULE_NAME_SSP","title":"MODULE_NAME_SSP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NAME","title":"NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NAMESPACE_FEDRAMP","title":"NAMESPACE_FEDRAMP","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NAMESPACE_NIST","title":"NAMESPACE_NIST","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NCNAME_REGEX","title":"NCNAME_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NCNAME_UTF8_FIRST_CHAR_OPTIONS","title":"NCNAME_UTF8_FIRST_CHAR_OPTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.NCNAME_UTF8_OTHER_CHAR_OPTIONS","title":"NCNAME_UTF8_OTHER_CHAR_OPTIONS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.OBJECTIVE_PART","title":"OBJECTIVE_PART","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ONE","title":"ONE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ONE_OR_MORE_HYPHENED","title":"ONE_OR_MORE_HYPHENED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ONE_OR_MORE_SPACED","title":"ONE_OR_MORE_SPACED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_CUSTOMER_CONFIGURED","title":"ORIGINATION_CUSTOMER_CONFIGURED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_CUSTOMER_PROVIDED","title":"ORIGINATION_CUSTOMER_PROVIDED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_INHERITED","title":"ORIGINATION_INHERITED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_ORGANIZATION","title":"ORIGINATION_ORGANIZATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ORIGINATION_SYSTEM_SPECIFIC","title":"ORIGINATION_SYSTEM_SPECIFIC","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PACKAGE_OSCAL","title":"PACKAGE_OSCAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAMETER_DESCRIPTION","title":"PARAMETER_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAMETER_ID","title":"PARAMETER_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAMETER_VALUE_ALTERNATIVES","title":"PARAMETER_VALUE_ALTERNATIVES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAM_VALUES_TAG","title":"PARAM_VALUES_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PARAM_VALUE_ORIGIN","title":"PARAM_VALUE_ORIGIN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PART_REGEX","title":"PART_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE","title":"PROFILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT","title":"PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE_PARAM_VALUE_ORIGIN","title":"PROFILE_PARAM_VALUE_ORIGIN","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROFILE_VALUES","title":"PROFILE_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROPERTY_REGEX","title":"PROPERTY_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROVIDED_STATEMENT_DESCRIPTION","title":"PROVIDED_STATEMENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.PROVIDED_UUID","title":"PROVIDED_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.REMARKS","title":"REMARKS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.REPLACE_ME","title":"REPLACE_ME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.REPLACE_ME_PLACEHOLDER","title":"REPLACE_ME_PLACEHOLDER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESOLUTION_SOURCE","title":"RESOLUTION_SOURCE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBILITY_STATEMENT_DESCRIPTION","title":"RESPONSIBILITY_STATEMENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBILITY_UUID","title":"RESPONSIBILITY_UUID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBLE_ROLE","title":"RESPONSIBLE_ROLE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RESPONSIBLE_ROLES","title":"RESPONSIBLE_ROLES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.ROOT","title":"ROOT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULES_PARAMS_TAG","title":"RULES_PARAMS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULES_WARNING","title":"RULES_WARNING","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULE_DESCRIPTION","title":"RULE_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.RULE_ID","title":"RULE_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SAMPLE_UUID_STR","title":"SAMPLE_UUID_STR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SATISFIED_STATEMENT_COMMENT","title":"SATISFIED_STATEMENT_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SATISFIED_STATEMENT_DESCRIPTION","title":"SATISFIED_STATEMENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SECTIONS_TAG","title":"SECTIONS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SET_PARAMS_TAG","title":"SET_PARAMS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SFTP_URI","title":"SFTP_URI","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SORT_ID","title":"SORT_ID","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT","title":"SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_FOR_ITEM_TEXT","title":"SSP_ADD_IMPLEMENTATION_FOR_ITEM_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_FOR_STATEMENT_TEXT","title":"SSP_ADD_IMPLEMENTATION_FOR_STATEMENT_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_IMPLEMENTATION_PREFIX","title":"SSP_ADD_IMPLEMENTATION_PREFIX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT","title":"SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_FEDRAMP_TAG","title":"SSP_FEDRAMP_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MAIN_COMP_NAME","title":"SSP_MAIN_COMP_NAME","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MD_HRULE_LINE","title":"SSP_MD_HRULE_LINE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MD_IMPLEMENTATION_QUESTION","title":"SSP_MD_IMPLEMENTATION_QUESTION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_MD_LEAVE_BLANK_TEXT","title":"SSP_MD_LEAVE_BLANK_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_SYSTEM_CONTROL_IMPLEMENTATION_TEXT","title":"SSP_SYSTEM_CONTROL_IMPLEMENTATION_TEXT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.SSP_VALUES","title":"SSP_VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATEMENT","title":"STATEMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_ALL","title":"STATUS_ALL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_ALTERNATIVE","title":"STATUS_ALTERNATIVE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_COMPLETION_DATE","title":"STATUS_COMPLETION_DATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_DISPOSITION","title":"STATUS_DISPOSITION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_IMPLEMENTED","title":"STATUS_IMPLEMENTED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_INHERITED","title":"STATUS_INHERITED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_NOT_APPLICABLE","title":"STATUS_NOT_APPLICABLE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_OPERATIONAL","title":"STATUS_OPERATIONAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_OTHER","title":"STATUS_OTHER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PARTIAL","title":"STATUS_PARTIAL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PARTIALLY_IMPLEMENTED","title":"STATUS_PARTIALLY_IMPLEMENTED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PLANNED","title":"STATUS_PLANNED","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PLANNED_COMPLETION_DATE","title":"STATUS_PLANNED_COMPLETION_DATE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_PROMPT","title":"STATUS_PROMPT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_REMARKS","title":"STATUS_REMARKS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_UNDER_DEVELOPMENT","title":"STATUS_UNDER_DEVELOPMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.STATUS_UNDER_MAJOR_MODIFICATION","title":"STATUS_UNDER_MAJOR_MODIFICATION","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TABLE_OF_PARAMS_PART","title":"TABLE_OF_PARAMS_PART","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TEMPLATE_VERSION_REGEX","title":"TEMPLATE_VERSION_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.THIS_SYSTEM_AS_KEY","title":"THIS_SYSTEM_AS_KEY","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.THIS_SYSTEM_PROMPT","title":"THIS_SYSTEM_PROMPT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TITLE","title":"TITLE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRANSFORM_TYPES","title":"TRANSFORM_TYPES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_ADD_PROPS_TAG","title":"TRESTLE_ADD_PROPS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_CACHE_DIR","title":"TRESTLE_CACHE_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_CONFIG_DIR","title":"TRESTLE_CONFIG_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_CONFIG_FILE","title":"TRESTLE_CONFIG_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_DIST_DIR","title":"TRESTLE_DIST_DIR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_GENERIC_NS","title":"TRESTLE_GENERIC_NS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_GLOBAL_TAG","title":"TRESTLE_GLOBAL_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_HREF_HEADING","title":"TRESTLE_HREF_HEADING","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_HREF_REGEX","title":"TRESTLE_HREF_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_IMP_STATUS_TAG","title":"TRESTLE_IMP_STATUS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_INHERITED_PROPS_TAG","title":"TRESTLE_INHERITED_PROPS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_INHERITED_PROPS_TRACKER","title":"TRESTLE_INHERITED_PROPS_TRACKER","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_KEEP_FILE","title":"TRESTLE_KEEP_FILE","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_LEVERAGING_COMP_TAG","title":"TRESTLE_LEVERAGING_COMP_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_PROPS_TAG","title":"TRESTLE_PROPS_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_STATEMENT_TAG","title":"TRESTLE_STATEMENT_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.TRESTLE_TAG","title":"TRESTLE_TAG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.UNIX_CACHE_ROOT","title":"UNIX_CACHE_ROOT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.UUID_REGEX","title":"UUID_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VALUES","title":"VALUES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VALUE_ASSIGNED_PREFIX","title":"VALUE_ASSIGNED_PREFIX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VALUE_NOT_ASSIGNED_PREFIX","title":"VALUE_NOT_ASSIGNED_PREFIX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_ALL","title":"VAL_MODE_ALL","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_CATALOG","title":"VAL_MODE_CATALOG","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_DUPLICATES","title":"VAL_MODE_DUPLICATES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_LINKS","title":"VAL_MODE_LINKS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_REFS","title":"VAL_MODE_REFS","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.VAL_MODE_RULES","title":"VAL_MODE_RULES","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WEBSITE_ROOT","title":"WEBSITE_ROOT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WINDOWS_DRIVE_LETTER_REGEX","title":"WINDOWS_DRIVE_LETTER_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WINDOWS_DRIVE_URI_REGEX","title":"WINDOWS_DRIVE_URI_REGEX","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.WINDOWS_PLATFORM_STR","title":"WINDOWS_PLATFORM_STR","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_LEVERAGED_COMMENT","title":"YAML_LEVERAGED_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_LEVERAGING_COMP_COMMENT","title":"YAML_LEVERAGING_COMP_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_PROFILE_VALUES_COMMENT","title":"YAML_PROFILE_VALUES_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_PROPS_COMMENT","title":"YAML_PROPS_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT","title":"YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_RULE_PARAM_VALUES_SSP_COMMENT","title":"YAML_RULE_PARAM_VALUES_SSP_COMMENT","text":""},{"location":"api_reference/trestle.common.const/#trestle.common.const.YAML_SSP_VALUES_COMMENT","title":"YAML_SSP_VALUES_COMMENT","text":""},{"location":"api_reference/trestle.common.err/","title":"err","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err","title":"trestle.common.err","text":"

                                                                            Trestle core errors module.

                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError","title":" TrestleError (RuntimeError) ","text":"

                                                                            General framework (non-application) related errors.

                                                                            Attributes:

                                                                            Name Type Description msg str

                                                                            Human readable string describing the exception.

                                                                            Source code in trestle/common/err.py
                                                                            class TrestleError(RuntimeError):\n\"\"\"\n    General framework (non-application) related errors.\n\n    Attributes:\n        msg (str): Human readable string describing the exception.\n    \"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"Intialization for TresleError.\n\n        Args:\n            msg (str): The error message\n        \"\"\"\n        RuntimeError.__init__(self)\n        self.msg = msg\n\n    def __str__(self) -> str:\n\"\"\"Return Trestle error message if asked for a string.\"\"\"\n        return self.msg\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError.__init__","title":"__init__(self, msg) special","text":"

                                                                            Intialization for TresleError.

                                                                            Parameters:

                                                                            Name Type Description Default msg str

                                                                            The error message

                                                                            required Source code in trestle/common/err.py
                                                                            def __init__(self, msg: str):\n\"\"\"Intialization for TresleError.\n\n    Args:\n        msg (str): The error message\n    \"\"\"\n    RuntimeError.__init__(self)\n    self.msg = msg\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleError.__str__","title":"__str__(self) special","text":"

                                                                            Return Trestle error message if asked for a string.

                                                                            Source code in trestle/common/err.py
                                                                            def __str__(self) -> str:\n\"\"\"Return Trestle error message if asked for a string.\"\"\"\n    return self.msg\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleIncorrectArgsError","title":" TrestleIncorrectArgsError (TrestleError) ","text":"

                                                                            General error for incorrect args passed to Trestle command.

                                                                            Source code in trestle/common/err.py
                                                                            class TrestleIncorrectArgsError(TrestleError):\n\"\"\"General error for incorrect args passed to Trestle command.\"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"\n        Initialize TrestleIncorrectArgsError.\n\n        Args:\n            msg (str): The error message\n        \"\"\"\n        super().__init__(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleIncorrectArgsError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleIncorrectArgsError.__init__","title":"__init__(self, msg) special","text":"

                                                                            Initialize TrestleIncorrectArgsError.

                                                                            Parameters:

                                                                            Name Type Description Default msg str

                                                                            The error message

                                                                            required Source code in trestle/common/err.py
                                                                            def __init__(self, msg: str):\n\"\"\"\n    Initialize TrestleIncorrectArgsError.\n\n    Args:\n        msg (str): The error message\n    \"\"\"\n    super().__init__(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleNotFoundError","title":" TrestleNotFoundError (TrestleError) ","text":"

                                                                            General framework related not found error.

                                                                            Attributes:

                                                                            Name Type Description msg str

                                                                            Human readable string describing the exception.

                                                                            Source code in trestle/common/err.py
                                                                            class TrestleNotFoundError(TrestleError):\n\"\"\"\n    General framework related not found error.\n\n    Attributes:\n        msg (str): Human readable string describing the exception.\n    \"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"\n        Intialize TresleNotFoundError.\n\n        Args:\n            msg: The error message\n        \"\"\"\n        super().__init__(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleNotFoundError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleNotFoundError.__init__","title":"__init__(self, msg) special","text":"

                                                                            Intialize TresleNotFoundError.

                                                                            Parameters:

                                                                            Name Type Description Default msg str

                                                                            The error message

                                                                            required Source code in trestle/common/err.py
                                                                            def __init__(self, msg: str):\n\"\"\"\n    Intialize TresleNotFoundError.\n\n    Args:\n        msg: The error message\n    \"\"\"\n    super().__init__(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleRootError","title":" TrestleRootError (TrestleError) ","text":"

                                                                            General error for trestle workspace root/setup errors.

                                                                            Source code in trestle/common/err.py
                                                                            class TrestleRootError(TrestleError):\n\"\"\"General error for trestle workspace root/setup errors.\"\"\"\n\n    def __init__(self, msg: str):\n\"\"\"\n        Initialize TrestleRootError.\n\n        Args:\n            msg (str): The error message\n        \"\"\"\n        super().__init__(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleRootError-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.TrestleRootError.__init__","title":"__init__(self, msg) special","text":"

                                                                            Initialize TrestleRootError.

                                                                            Parameters:

                                                                            Name Type Description Default msg str

                                                                            The error message

                                                                            required Source code in trestle/common/err.py
                                                                            def __init__(self, msg: str):\n\"\"\"\n    Initialize TrestleRootError.\n\n    Args:\n        msg (str): The error message\n    \"\"\"\n    super().__init__(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.err/#trestle.common.err-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.err/#trestle.common.err.handle_generic_command_exception","title":"handle_generic_command_exception(exception, logger, msg='Exception occured during execution')","text":"

                                                                            Print out error message based on the verbosity and return appropriate status code.

                                                                            Source code in trestle/common/err.py
                                                                            def handle_generic_command_exception(\n    exception: Exception, logger: Logger, msg: str = 'Exception occured during execution'\n) -> int:\n\"\"\"Print out error message based on the verbosity and return appropriate status code.\"\"\"\n    if get_current_verbosity_level(logger) == 0:\n        logger.error(msg + f': {exception}')\n    else:\n        logger.exception(msg + f': {exception}')\n\n    return _exception_to_error_code(exception)\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/","title":"file_utils","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils","title":"trestle.common.file_utils","text":"

                                                                            Trestle file system utils.

                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.check_oscal_directories","title":"check_oscal_directories(root_path)","text":"

                                                                            Identify the state of the trestle workspace.

                                                                            Traverses trestle workspace and looks for unexpected files or directories. Additional files are allowed in the Trestle root but not inside the model folders.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def check_oscal_directories(root_path: pathlib.Path) -> bool:\n\"\"\"\n    Identify the state of the trestle workspace.\n\n    Traverses trestle workspace and looks for unexpected files or directories.\n    Additional files are allowed in the Trestle root but not inside the model folders.\n    \"\"\"\n    trestle_dir_walk = os.walk(root_path)\n    is_valid = True\n\n    for _, dirs, _ in trestle_dir_walk:\n        for d in dirs:\n            if d in MODEL_DIR_LIST:\n                is_valid = _verify_oscal_folder(root_path / d)\n                if not is_valid:\n                    break\n    return is_valid\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.extract_project_model_path","title":"extract_project_model_path(path)","text":"

                                                                            Get the base path of the trestle model project.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def extract_project_model_path(path: pathlib.Path) -> Optional[pathlib.Path]:\n\"\"\"Get the base path of the trestle model project.\"\"\"\n    if len(path.parts) > 2:\n        for i in range(2, len(path.parts)):\n            current = pathlib.Path(path.parts[0]).joinpath(*path.parts[1:i + 1])\n            if _is_valid_project_model_path(current):\n                return current\n    return None\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.extract_trestle_project_root","title":"extract_trestle_project_root(path)","text":"

                                                                            Get the trestle workspace root folder in the path.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def extract_trestle_project_root(path: pathlib.Path) -> Optional[pathlib.Path]:\n\"\"\"Get the trestle workspace root folder in the path.\"\"\"\n    while len(path.parts) > 1:  # it must not be the system root directory\n        if is_valid_project_root(path):\n            return path\n        path = path.parent\n    return None\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.get_contextual_file_type","title":"get_contextual_file_type(path)","text":"

                                                                            Return the file content type for files in the given directory, if it's a trestle workspace.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def get_contextual_file_type(path: pathlib.Path) -> FileContentType:\n\"\"\"Return the file content type for files in the given directory, if it's a trestle workspace.\"\"\"\n    if not _is_valid_project_model_path(path):\n        raise err.TrestleError(f'Trestle workspace not found at path {path}')\n\n    for file_or_directory in iterdir_without_hidden_files(path):\n        if file_or_directory.is_file():\n            return FileContentType.to_content_type(file_or_directory.suffix)\n\n    for file_or_directory in path.iterdir():\n        if file_or_directory.is_dir():\n            return get_contextual_file_type(file_or_directory)\n\n    raise err.TrestleError('No files found in the project.')\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.insert_text_in_file","title":"insert_text_in_file(file_path, tag, text)","text":"

                                                                            Insert text lines after line containing tag.

                                                                            Return True on success, False tag not found. Text is a string with appropriate \\n line endings. If tag is none just add at end of file. This will only open file once if tag is not found.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def insert_text_in_file(file_path: pathlib.Path, tag: Optional[str], text: str) -> bool:\nr\"\"\"Insert text lines after line containing tag.\n\n    Return True on success, False tag not found.\n    Text is a string with appropriate \\n line endings.\n    If tag is none just add at end of file.\n    This will only open file once if tag is not found.\n    \"\"\"\n    if not file_path.exists():\n        raise TrestleError(f'Test file {file_path} not found.')\n    if tag:\n        lines: List[str] = []\n        with file_path.open('r', encoding=const.FILE_ENCODING) as f:\n            lines = f.readlines()\n        for ii, line in enumerate(lines):\n            if line.find(tag) >= 0:\n                lines.insert(ii + 1, text)\n                with file_path.open('w', encoding=const.FILE_ENCODING) as f:\n                    f.writelines(lines)\n                return True\n    else:\n        with file_path.open('a', encoding=const.FILE_ENCODING) as f:\n            f.writelines(text)\n        return True\n    return False\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_directory_name_allowed","title":"is_directory_name_allowed(name)","text":"

                                                                            Determine whether a directory name, which is a 'non-core-OSCAL activity/directory is allowed.

                                                                            Parameters:

                                                                            Name Type Description Default name str

                                                                            the name which is assumed may take the form of a relative path for task/subtasks.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            Whether the name is allowed or not allowed (interferes with assumed project directories such as catalogs).

                                                                            Source code in trestle/common/file_utils.py
                                                                            def is_directory_name_allowed(name: str) -> bool:\n\"\"\"Determine whether a directory name, which is a 'non-core-OSCAL activity/directory is allowed.\n\n    args:\n        name: the name which is assumed may take the form of a relative path for task/subtasks.\n\n    Returns:\n        Whether the name is allowed or not allowed (interferes with assumed project directories such as catalogs).\n    \"\"\"\n    # Task must not use an OSCAL directory\n    # Task must not self-interfere with a project\n    pathed_name = pathlib.Path(name)\n\n    root_path = pathed_name.parts[0]\n    if root_path in const.MODEL_TYPE_TO_MODEL_DIR.values():\n        logger.warning('Task name is the same as an OSCAL schema name.')\n        return False\n    if root_path[0] == '.':\n        logger.warning('Task name must not start with \".\"')\n        return False\n    if pathed_name.suffix != '':\n        # Does it look like a file\n        logger.warning('Task name must not look like a file path (e.g. contain a suffix')\n        return False\n    if '__global__' in pathed_name.parts:\n        logger.warning('Task name cannot contain __global__')\n        return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_hidden","title":"is_hidden(file_path)","text":"

                                                                            Determine whether a file is hidden based on the appropriate os attributes.

                                                                            This function will only work for the current file path only (e.g. not if a parent is hidden).

                                                                            Parameters:

                                                                            Name Type Description Default file_path Path

                                                                            The file path for which we are testing whether the file / directory is hidden.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            Whether or not the file is file/directory is hidden.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def is_hidden(file_path: pathlib.Path) -> bool:\n\"\"\"\n    Determine whether a file is hidden based on the appropriate os attributes.\n\n    This function will only work for the current file path only (e.g. not if a parent is hidden).\n\n    Args:\n        file_path: The file path for which we are testing whether the file / directory is hidden.\n\n    Returns:\n        Whether or not the file is file/directory is hidden.\n    \"\"\"\n    # as far as trestle is concerned all .* files are hidden even on windows, regardless of attributes\n    if file_path.stem.startswith('.'):\n        return True\n    # Handle windows\n    if is_windows():  # pragma: no cover\n        attribute = win32api.GetFileAttributes(str(file_path))\n        return attribute & (win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM)\n    return False\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_local_and_visible","title":"is_local_and_visible(file_path)","text":"

                                                                            Is the file or dir local (not a symlink) and not hidden.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def is_local_and_visible(file_path: pathlib.Path) -> bool:\n\"\"\"Is the file or dir local (not a symlink) and not hidden.\"\"\"\n    return not (is_hidden(file_path) or is_symlink(file_path))\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_symlink","title":"is_symlink(file_path)","text":"

                                                                            Is the file path a symlink.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def is_symlink(file_path: pathlib.Path) -> bool:\n\"\"\"Is the file path a symlink.\"\"\"\n    if is_windows():\n        return file_path.suffix == '.lnk'\n    return file_path.is_symlink()\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_valid_project_root","title":"is_valid_project_root(path)","text":"

                                                                            Check if the path is a valid trestle workspace root.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def is_valid_project_root(path: pathlib.Path) -> bool:\n\"\"\"Check if the path is a valid trestle workspace root.\"\"\"\n    trestle_dir = path / const.TRESTLE_CONFIG_DIR\n    return trestle_dir.exists() and trestle_dir.is_dir()\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.is_windows","title":"is_windows()","text":"

                                                                            Check if current operating system is Windows.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def is_windows() -> bool:\n\"\"\"Check if current operating system is Windows.\"\"\"\n    return platform.system() == const.WINDOWS_PLATFORM_STR\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.iterdir_without_hidden_files","title":"iterdir_without_hidden_files(directory_path)","text":"

                                                                            Get iterator over all paths in the given directory_path excluding hidden files.

                                                                            Parameters:

                                                                            Name Type Description Default directory_path Path

                                                                            The directory to iterate through.

                                                                            required

                                                                            Returns:

                                                                            Type Description Iterable[pathlib.Path]

                                                                            Iterator over the files in the directory excluding hidden files.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def iterdir_without_hidden_files(directory_path: pathlib.Path) -> Iterable[pathlib.Path]:\n\"\"\"\n    Get iterator over all paths in the given directory_path excluding hidden files.\n\n    Args:\n        directory_path: The directory to iterate through.\n\n    Returns:\n        Iterator over the files in the directory excluding hidden files.\n    \"\"\"\n    filtered_paths = list(filter(lambda p: not is_hidden(p) or p.is_dir(), pathlib.Path.iterdir(directory_path)))\n\n    return filtered_paths.__iter__()\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.load_file","title":"load_file(file_path)","text":"

                                                                            Load JSON or YAML file content into a dict.

                                                                            This is not intended to be the default load mechanism. It should only be used if a OSCAL object type is unknown but the context a user is in.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def load_file(file_path: pathlib.Path) -> Dict[str, Any]:\n\"\"\"\n    Load JSON or YAML file content into a dict.\n\n    This is not intended to be the default load mechanism. It should only be used\n    if a OSCAL object type is unknown but the context a user is in.\n    \"\"\"\n    content_type = FileContentType.to_content_type(file_path.suffix)\n    with file_path.open('r', encoding=const.FILE_ENCODING) as f:\n        if content_type == FileContentType.YAML:\n            yaml = YAML(typ='safe')\n            return yaml.load(f)\n        if content_type == FileContentType.JSON:\n            return json.load(f)\n    return {}\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.make_hidden_file","title":"make_hidden_file(file_path)","text":"

                                                                            Make hidden file.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def make_hidden_file(file_path: pathlib.Path) -> None:\n\"\"\"Make hidden file.\"\"\"\n    if not file_path.name.startswith('.') and not is_windows():\n        file_path = file_path.parent / ('.' + file_path.name)\n\n    file_path.touch()\n    if is_windows():\n        atts = win32api.GetFileAttributes(str(file_path))\n        win32api.SetFileAttributes(str(file_path), win32con.FILE_ATTRIBUTE_HIDDEN | atts)\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.prune_empty_dirs","title":"prune_empty_dirs(file_path, pattern)","text":"

                                                                            Remove directories with no subdirs and with no files matching pattern.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def prune_empty_dirs(file_path: pathlib.Path, pattern: str) -> None:\n\"\"\"Remove directories with no subdirs and with no files matching pattern.\"\"\"\n    deleted: Set[str] = set()\n    # this traverses from leaf nodes upward so only needs one traversal\n    for current_dir, subdirs, _ in os.walk(str(file_path), topdown=False):\n        true_dirs = [subdir for subdir in subdirs if os.path.join(current_dir, subdir) not in deleted]\n        if not true_dirs and not any(glob.glob(f'{current_dir}/{pattern}')):\n            shutil.rmtree(current_dir)\n            deleted.add(current_dir)\n
                                                                            "},{"location":"api_reference/trestle.common.file_utils/#trestle.common.file_utils.relative_resolve","title":"relative_resolve(candidate, cwd)","text":"

                                                                            Resolve a candidate file path relative to a provided cwd.

                                                                            This is to circumvent bad behaviour for resolve on windows platforms where the path must exist.

                                                                            If a relative dir is passed it presumes the directory is relative to the PROVIDED cwd. If relative expansions exist (e.g. ../) the final result must still be within the cwd.

                                                                            If an absolute path is provided it tests whether the path is within the cwd or not.

                                                                            Source code in trestle/common/file_utils.py
                                                                            def relative_resolve(candidate: pathlib.Path, cwd: pathlib.Path) -> pathlib.Path:\n\"\"\"Resolve a candidate file path relative to a provided cwd.\n\n    This is to circumvent bad behaviour for resolve on windows platforms where the path must exist.\n\n    If a relative dir is passed it presumes the directory is relative to the PROVIDED cwd.\n    If relative expansions exist (e.g. ../) the final result must still be within the cwd.\n\n    If an absolute path is provided it tests whether the path is within the cwd or not.\n\n    \"\"\"\n    # Expand user first if applicable.\n    candidate = candidate.expanduser()\n\n    if not cwd.is_absolute():\n        raise TrestleError('Error handling current working directory. CWD is expected to be absolute.')\n\n    if not candidate.is_absolute():\n        new = pathlib.Path(cwd / candidate).resolve()\n    else:\n        new = candidate.resolve()\n    try:\n        new.relative_to(cwd)\n    except ValueError:\n        raise TrestleError(f'Provided dir {candidate} is not relative to {cwd}')\n    return new\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/","title":"list_utils","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils","title":"trestle.common.list_utils","text":"

                                                                            Trestle List Utils.

                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.as_dict","title":"as_dict(dict_or_none)","text":"

                                                                            Convert dict or None object to itself or an empty dict if none.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def as_dict(dict_or_none: Optional[Dict[TG, TG2]]) -> Dict[TG, TG2]:\n\"\"\"Convert dict or None object to itself or an empty dict if none.\"\"\"\n    return dict_or_none if dict_or_none else {}\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.as_filtered_list","title":"as_filtered_list(list_or_none, filter_condition)","text":"

                                                                            Convert to list and filter based on the condition.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def as_filtered_list(list_or_none: Optional[List[TG]], filter_condition: Callable[[TG], bool]) -> List[TG]:\n\"\"\"Convert to list and filter based on the condition.\"\"\"\n    result_list = as_list(list_or_none)\n    result_list = list(filter(filter_condition, result_list))\n    return result_list\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.as_list","title":"as_list(list_or_none)","text":"

                                                                            Convert list or None object to itself or an empty list if none.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def as_list(list_or_none: Optional[List[TG]]) -> List[TG]:\n\"\"\"Convert list or None object to itself or an empty list if none.\"\"\"\n    return list_or_none if list_or_none else []\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.comma_colon_sep_to_dict","title":"comma_colon_sep_to_dict(string_or_none)","text":"

                                                                            Convert optional comma and colon-sep list to dict.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def comma_colon_sep_to_dict(string_or_none: Optional[str]) -> Dict[str, str]:\n\"\"\"Convert optional comma and colon-sep list to dict.\"\"\"\n    entries = comma_sep_to_list(string_or_none)\n    dic = {}\n    for entry in entries:\n        # if more than one colon include any colons in the value after the first one\n        token = entry.split(':', 1)\n        if len(token) == 1:\n            dic[token[0].strip()] = token[0].strip()\n        else:\n            dic[token[0].strip()] = token[1].strip()\n    return dic\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.comma_sep_to_list","title":"comma_sep_to_list(string_or_none)","text":"

                                                                            Convert optional comma-sep string to list of strings and strip.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def comma_sep_to_list(string_or_none: Optional[str]) -> List[str]:\n\"\"\"Convert optional comma-sep string to list of strings and strip.\"\"\"\n    string_or_none = string_or_none.strip() if string_or_none else None\n    return list(map(str.strip, string_or_none.split(','))) if string_or_none else []\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_append","title":"deep_append(dic, path, value)","text":"

                                                                            Append to list in dict.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def deep_append(dic: Dict[str, Any], path: List[str], value: Any) -> None:\n\"\"\"Append to list in dict.\"\"\"\n    if not path:\n        raise TrestleError('Error appending value in deep append with empty path.')\n    for node in path[:-1]:\n        dic[node] = dic.get(node, {})\n        dic = dic[node]\n    if path[-1] not in dic:\n        dic[path[-1]] = []\n    dic[path[-1]].append(value)\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_get","title":"deep_get(dic, path, default=None)","text":"

                                                                            Get value from deep in dictionary.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def deep_get(dic: Dict[str, Any], path: List[str], default: Any = None) -> Any:\n\"\"\"Get value from deep in dictionary.\"\"\"\n    if not path:\n        raise TrestleError('Error getting value in deep get with empty path.')\n    for node in path[:-1]:\n        if node not in dic:\n            return default\n        dic = dic[node]\n    return dic.get(path[-1], default)\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_set","title":"deep_set(dic, path, value, pop_if_none=True)","text":"

                                                                            Set value deep in dictionary.

                                                                            pop_if_none will cause the key to be removed if value is None

                                                                            Source code in trestle/common/list_utils.py
                                                                            def deep_set(dic: Dict[str, Any], path: List[str], value: Any, pop_if_none: bool = True) -> None:\n\"\"\"\n    Set value deep in dictionary.\n\n    pop_if_none will cause the key to be removed if value is None\n    \"\"\"\n    if not path:\n        raise TrestleError('Error setting value in deep set with empty path.')\n    for node in path[:-1]:\n        dic[node] = dic.get(node, {})\n        dic = dic[node]\n    if value or not pop_if_none:\n        dic[path[-1]] = value\n    else:\n        dic.pop(path[-1], None)\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.deep_update","title":"deep_update(dic, path, dic_value)","text":"

                                                                            Update the dict based on path.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def deep_update(dic: Dict[str, Any], path: List[str], dic_value: Dict[str, Any]) -> None:\n\"\"\"Update the dict based on path.\"\"\"\n    if not path:\n        raise TrestleError('Error updating value in deep update with empty path.')\n    for node in path:\n        dic[node] = dic.get(node, {})\n        dic = dic[node]\n    dic.update(dic_value)\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.delete_item_from_list","title":"delete_item_from_list(item_list, value, key)","text":"

                                                                            Remove the first matching item if it is present in a list based on the callable key matching the query value.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def delete_item_from_list(item_list: List[TG], value: TG2, key: Callable[[TG], TG2]) -> List[TG]:\n\"\"\"Remove the first matching item if it is present in a list based on the callable key matching the query value.\"\"\"\n    keys = [key(item) for item in item_list]\n    if value in keys:\n        index = keys.index(value)\n        del item_list[index]\n    return item_list\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.delete_list_from_list","title":"delete_list_from_list(item_list, indices)","text":"

                                                                            Delete a list of items from a list based on indices.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def delete_list_from_list(item_list: List[TG], indices: List[int]) -> None:\n\"\"\"Delete a list of items from a list based on indices.\"\"\"\n    for index in sorted(indices, reverse=True):\n        del item_list[index]\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.get_default","title":"get_default(item, default)","text":"

                                                                            Return the default value for the item if it is not set.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def get_default(item: TG, default: TG) -> TG:\n\"\"\"Return the default value for the item if it is not set.\"\"\"\n    return item if item else default\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.get_item_from_list","title":"get_item_from_list(item_list, value, key, remove=False)","text":"

                                                                            Get first item from list if present based on key matching value with option to remove it from the list.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def get_item_from_list(item_list: Optional[List[TG]],\n                       value: TG2,\n                       key: Callable[[TG], TG2],\n                       remove: bool = False) -> Optional[TG]:\n\"\"\"Get first item from list if present based on key matching value with option to remove it from the list.\"\"\"\n    if not item_list:\n        return None\n    keys = [key(item) for item in item_list]\n    item = None\n    if value in keys:\n        index = keys.index(value)\n        item = item_list[index]\n        if remove:\n            del item_list[index]\n    return item\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.is_ordered_sublist","title":"is_ordered_sublist(needle, haystack)","text":"

                                                                            Determine if needle is exactly contained in haystack.

                                                                            The needle list comprises an ordered list of strings. The haystack list comprises an ordered list of strings that is to be searched. If the strings in the needle appear in the haystack in that exact order then return true, else false.

                                                                            Examples:

                                                                            needle=['a','b','c'], haystack=['x','y','a','b','c','z'], result = True needle=['a','b','c'], haystack=['x','y','a','b','z','c'], result = False

                                                                            Source code in trestle/common/list_utils.py
                                                                            def is_ordered_sublist(needle: List[str], haystack: List[str]) -> bool:\n\"\"\"Determine if needle is exactly contained in haystack.\n\n    The needle list comprises an ordered list of strings.\n    The haystack list comprises an ordered list of strings that is to be searched.\n    If the strings in the needle appear in the haystack in that exact order then\n    return true, else false.\n\n    Examples:\n    needle=['a','b','c'], haystack=['x','y','a','b','c','z'], result = True\n    needle=['a','b','c'], haystack=['x','y','a','b','z','c'], result = False\n    \"\"\"\n    return ' '.join(needle) in ' '.join(haystack)\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.join_key_to_list_dicts","title":"join_key_to_list_dicts(dict1, dict2)","text":"

                                                                            Join two dicts of str to List.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def join_key_to_list_dicts(dict1: Dict[str, List[Any]], dict2: Dict[str, List[Any]]) -> Dict[str, List[Any]]:\n\"\"\"Join two dicts of str to List.\"\"\"\n    # merge like keys\n    dict3 = {key: dict1[key] + dict2.get(key, []) for key in dict1}\n    # merge unlike keys\n    dict3.update({key: dict2[key] for key in dict2 if key not in dict3})\n    return dict3\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.merge_dicts","title":"merge_dicts(dest, src)","text":"

                                                                            Merge the two dicts with priority to src.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def merge_dicts(dest: Optional[Dict[str, str]], src: Optional[Dict[str, str]]) -> Dict[str, str]:\n\"\"\"Merge the two dicts with priority to src.\"\"\"\n    return {**as_dict(dest), **as_dict(src)}\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.none_if_empty","title":"none_if_empty(list_)","text":"

                                                                            Convert to None if empty list.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def none_if_empty(list_: List[TG]) -> Optional[List[TG]]:\n\"\"\"Convert to None if empty list.\"\"\"\n    return list_ if list_ else None\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.pop_item_from_list","title":"pop_item_from_list(item_list, value, key)","text":"

                                                                            Pop first matching item from a list if it is present based on the key matching the value.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def pop_item_from_list(item_list: Optional[List[TG]], value: TG2, key: Callable[[TG], TG2]) -> Optional[TG]:\n\"\"\"Pop first matching item from a list if it is present based on the key matching the value.\"\"\"\n    return get_item_from_list(item_list, value, key, True)\n
                                                                            "},{"location":"api_reference/trestle.common.list_utils/#trestle.common.list_utils.set_or_pop","title":"set_or_pop(dic, key, value)","text":"

                                                                            Set if value is non-empty list or not None otherwise remove.

                                                                            Source code in trestle/common/list_utils.py
                                                                            def set_or_pop(dic: Dict[str, Any], key: str, value: Any) -> None:\n\"\"\"Set if value is non-empty list or not None otherwise remove.\"\"\"\n    if value:\n        dic[key] = value\n    else:\n        dic.pop(key, None)\n
                                                                            "},{"location":"api_reference/trestle.common.load_validate/","title":"load_validate","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate","title":"trestle.common.load_validate","text":"

                                                                            Function to load and validate files while avoiding circular imports.

                                                                            "},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate.load_validate_model_name","title":"load_validate_model_name(trestle_root, model_name, model_class, file_content_type=None)","text":"

                                                                            Load a model by its name and type and validate it.

                                                                            Source code in trestle/common/load_validate.py
                                                                            def load_validate_model_name(\n    trestle_root: Path,\n    model_name: str,\n    model_class: TG,\n    file_content_type: Optional[FileContentType] = None\n) -> Tuple[TG, Path]:\n\"\"\"Load a model by its name and type and validate it.\"\"\"\n    model_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, model_name, model_class, file_content_type)\n    model = load_validate_model_path(trestle_root, model_path)\n    return model, model_path\n
                                                                            "},{"location":"api_reference/trestle.common.load_validate/#trestle.common.load_validate.load_validate_model_path","title":"load_validate_model_path(trestle_root, model_path)","text":"

                                                                            Load a model by its path and validate it.

                                                                            Source code in trestle/common/load_validate.py
                                                                            def load_validate_model_path(trestle_root: Path, model_path: Path) -> TopLevelOscalModel:\n\"\"\"Load a model by its path and validate it.\"\"\"\n    _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n    args = argparse.Namespace(mode=const.VAL_MODE_ALL, quiet=True)\n    validator: Validator = validator_factory.get(args)\n    if not validator.model_is_valid(model, True, trestle_root):\n        logger.warning(f'Model loaded at {model_path} fails validation, but is being loaded anyway.')\n    return model\n
                                                                            "},{"location":"api_reference/trestle.common.log/","title":"log","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log","title":"trestle.common.log","text":"

                                                                            Common logging utilities.

                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter","title":" SpecificLevelFilter (Filter) ","text":"

                                                                            Filter for the same level as provided by setLevel for a log handler.

                                                                            Python by default logs all levels above to a given destination. This makes it easy to split levels where you might log all levels to file and only errors to std.err, however, does not allow logging a specific level elsewhere.

                                                                            Source code in trestle/common/log.py
                                                                            class SpecificLevelFilter(logging.Filter):\n\"\"\"\n    Filter for the same level as provided by setLevel for a log handler.\n\n    Python by default logs all levels above to a given destination. This makes it easy to split levels where you might\n    log all levels to file and only errors to std.err, however, does not allow logging a specific level elsewhere.\n    \"\"\"\n\n    def __init__(self, level: int) -> None:\n\"\"\"Initialize providing maximum level to be pushed through the filter.\"\"\"\n        self._level = level\n\n    def filter(self, log_record: logging.LogRecord) -> bool:  # noqa: A003\n\"\"\"Filter log messages.\"\"\"\n        return log_record.levelno == self._level\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter.__init__","title":"__init__(self, level) special","text":"

                                                                            Initialize providing maximum level to be pushed through the filter.

                                                                            Source code in trestle/common/log.py
                                                                            def __init__(self, level: int) -> None:\n\"\"\"Initialize providing maximum level to be pushed through the filter.\"\"\"\n    self._level = level\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log.SpecificLevelFilter.filter","title":"filter(self, log_record)","text":"

                                                                            Filter log messages.

                                                                            Source code in trestle/common/log.py
                                                                            def filter(self, log_record: logging.LogRecord) -> bool:  # noqa: A003\n\"\"\"Filter log messages.\"\"\"\n    return log_record.levelno == self._level\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace","title":" Trace ","text":"

                                                                            Class allowing low priority trace message when verbose > 1 and log level below DEBUG.

                                                                            Source code in trestle/common/log.py
                                                                            class Trace():\n\"\"\"Class allowing low priority trace message when verbose > 1 and log level below DEBUG.\"\"\"\n\n    def __init__(self, logger: logging.Logger) -> None:\n\"\"\"Store the main logger with its module name.\"\"\"\n        self._logger = logger\n\n    def log(self, msg: str) -> None:\n\"\"\"Output the trace msg if log level is below DEBUG.\"\"\"\n        level = self._logger.getEffectiveLevel()\n        if level < logging.DEBUG:\n            self._logger.debug(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace.__init__","title":"__init__(self, logger) special","text":"

                                                                            Store the main logger with its module name.

                                                                            Source code in trestle/common/log.py
                                                                            def __init__(self, logger: logging.Logger) -> None:\n\"\"\"Store the main logger with its module name.\"\"\"\n    self._logger = logger\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log.Trace.log","title":"log(self, msg)","text":"

                                                                            Output the trace msg if log level is below DEBUG.

                                                                            Source code in trestle/common/log.py
                                                                            def log(self, msg: str) -> None:\n\"\"\"Output the trace msg if log level is below DEBUG.\"\"\"\n    level = self._logger.getEffectiveLevel()\n    if level < logging.DEBUG:\n        self._logger.debug(msg)\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.log/#trestle.common.log.get_current_verbosity_level","title":"get_current_verbosity_level(logger)","text":"

                                                                            Get the current verbosity level based on logging level.

                                                                            Source code in trestle/common/log.py
                                                                            def get_current_verbosity_level(logger: logging.Logger) -> int:\n\"\"\"Get the current verbosity level based on logging level.\"\"\"\n    level = logger.getEffectiveLevel()\n    if level < logging.DEBUG:\n        return 2\n    elif level == logging.DEBUG:\n        return 1\n    return 0\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log.set_global_logging_levels","title":"set_global_logging_levels(level=20)","text":"

                                                                            Initialise logging.

                                                                            Should only be invoked by the CLI classes or similar.

                                                                            Source code in trestle/common/log.py
                                                                            def set_global_logging_levels(level: int = logging.INFO) -> None:\n\"\"\"Initialise logging.\n\n    Should only be invoked by the CLI classes or similar.\n    \"\"\"\n    # This line stops default root loggers setup for a python context from logging extra messages.\n    # DO NOT USE THIS COMMAND directly from an SDK. Handle logs levels based on your own application\n    _logger.propagate = False\n    # Remove handlers\n    _logger.handlers.clear()\n    # set global level\n    _logger.setLevel(level)\n    # Create standard out\n    console_out_handler = logging.StreamHandler(sys.stdout)\n    console_out_handler.setLevel(logging.INFO)\n    console_out_handler.addFilter(SpecificLevelFilter(logging.INFO))\n\n    console_debug_handler = logging.StreamHandler(sys.stdout)\n    console_debug_handler.setLevel(logging.DEBUG)\n    console_debug_handler.addFilter(SpecificLevelFilter(logging.DEBUG))\n\n    console_error_handler = logging.StreamHandler(sys.stderr)\n    console_error_handler.setLevel(logging.WARNING)\n    # create formatters\n    error_formatter = logging.Formatter('%(name)s:%(lineno)d %(levelname)s: %(message)s')\n    debug_formatter = logging.Formatter('%(name)s:%(lineno)d %(levelname)s: %(message)s')\n    console_debug_handler.setFormatter(debug_formatter)\n    console_error_handler.setFormatter(error_formatter)\n    # add ch to logger\n    _logger.addHandler(console_out_handler)\n    _logger.addHandler(console_error_handler)\n    _logger.addHandler(console_debug_handler)\n
                                                                            "},{"location":"api_reference/trestle.common.log/#trestle.common.log.set_log_level_from_args","title":"set_log_level_from_args(args)","text":"

                                                                            Vanity function to automatically set log levels based on verbosity flags.

                                                                            Source code in trestle/common/log.py
                                                                            def set_log_level_from_args(args: argparse.Namespace) -> None:\n\"\"\"Vanity function to automatically set log levels based on verbosity flags.\"\"\"\n    if args.verbose > 1:\n        # these msgs only output by trace calls\n        set_global_logging_levels(_get_trace_level())\n    elif args.verbose == 1:\n        set_global_logging_levels(logging.DEBUG)\n    else:\n        set_global_logging_levels(logging.INFO)\n        sys.excepthook = _exception_handler\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/","title":"model_utils","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils","title":"trestle.common.model_utils","text":"

                                                                            Common utilities for the OSCAL models and directories.

                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils","title":" ModelUtils ","text":"

                                                                            Utilities for the OSCAL models input and output.

                                                                            Source code in trestle/common/model_utils.py
                                                                            class ModelUtils:\n\"\"\"Utilities for the OSCAL models input and output.\"\"\"\n\n    @staticmethod\n    def load_distributed(\n        abs_path: Path,\n        abs_trestle_root: Path,\n        collection_type: Optional[Type[Any]] = None\n    ) -> Tuple[Type[OscalBaseModel],\n               str,\n               Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]]]:\n\"\"\"\n        Given path to a model, load the model.\n\n        If the model is decomposed/split/distributed,the decomposed models are loaded recursively.\n\n        Args:\n            abs_path: The path to the file/directory to be loaded.\n            abs_trestle_root: The trestle workspace root directory.\n            collection_type: The type of collection model, if it is a collection model.\n                typing.List is the only collection type handled or expected.\n                Defaults to None.\n\n        Returns:\n            Return a tuple of Model Type (e.g. class 'trestle.oscal.catalog.Catalog'),\n            Model Alias (e.g. 'catalog.metadata') and Instance of the Model.\n            If the model is decomposed/split/distributed, the instance of the model contains\n            the decomposed models loaded recursively.\n\n        Note:\n            This does not validate the model.  You must either validate the model separately or use the load_validate\n            utilities.\n        \"\"\"\n        # if trying to load file that does not exist, load path instead\n        if not abs_path.exists():\n            abs_path = abs_path.with_name(abs_path.stem)\n\n        if not abs_path.exists():\n            raise TrestleNotFoundError(f'File {abs_path} not found for load.')\n\n        if collection_type:\n            # If the path contains a list type model\n            if collection_type is list:\n                return ModelUtils._load_list(abs_path, abs_trestle_root)\n            # the only other collection type in OSCAL is dict, and it only applies to include_all,\n            # which is too granular ever to be loaded by this routine\n            else:\n                raise TrestleError(f'Collection type {collection_type} not recognized for distributed load.')\n\n        # Get current model\n        primary_model_type, primary_model_alias = ModelUtils.get_stripped_model_type(abs_path, abs_trestle_root)\n        primary_model_instance: Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]] = None\n\n        # is this an attempt to load an actual json or yaml file?\n        content_type = FileContentType.path_to_content_type(abs_path)\n        # if file is sought but it doesn't exist, ignore and load as decomposed model\n        if FileContentType.is_readable_file(content_type) and abs_path.exists():\n            primary_model_instance = primary_model_type.oscal_read(abs_path)\n        # Is model decomposed?\n        decomposed_dir = abs_path.with_name(abs_path.stem)\n\n        if decomposed_dir.exists():\n            aliases_not_to_be_stripped = []\n            instances_to_be_merged: List[OscalBaseModel] = []\n\n            for local_path in sorted(trestle.common.file_utils.iterdir_without_hidden_files(decomposed_dir)):\n                if local_path.is_file():\n                    model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path, abs_trestle_root)\n                    aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                    instances_to_be_merged.append(model_instance)\n\n                elif local_path.is_dir():\n                    model_type, model_alias = ModelUtils.get_stripped_model_type(local_path, abs_trestle_root)\n                    # Only load the directory if it is a collection model. Otherwise do nothing - it gets loaded when\n                    # iterating over the model file\n\n                    # If a model is just a container for a list e.g.\n                    # class Foo(OscalBaseModel):  noqa: E800\n                    #      __root__: List[Bar]    noqa: E800\n                    # You need to test whether first a root key exists\n                    # then whether the outer_type of root is a collection.\n                    # Alternative is to do a try except to avoid the error for an unknown key.\n\n                    if model_type.is_collection_container():\n                        # This directory is a decomposed List or Dict\n                        collection_type = model_type.get_collection_type()\n                        model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path,\n                                                                                              abs_trestle_root,\n                                                                                              collection_type)\n                        aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                        instances_to_be_merged.append(model_instance)\n            primary_model_dict = {}\n            if primary_model_instance is not None:\n                primary_model_dict = primary_model_instance.__dict__\n\n            merged_model_type, merged_model_alias = ModelUtils.get_stripped_model_type(abs_path,\n                                                                                       abs_trestle_root,\n                                                                                       aliases_not_to_be_stripped)\n\n            # The following use of top_level is to allow loading of a top level model by name only, e.g. MyCatalog\n            # There may be a better overall way to approach this.\n            top_level = len(merged_model_alias.split('.')) == 1\n\n            for i in range(len(aliases_not_to_be_stripped)):\n                alias = aliases_not_to_be_stripped[i]\n                instance = instances_to_be_merged[i]\n                if hasattr(instance, '__dict__') and '__root__' in instance.__dict__ and isinstance(instance,\n                                                                                                    OscalBaseModel):\n                    instance = instance.__dict__['__root__']\n                if top_level and not primary_model_dict:\n                    primary_model_dict = instance.__dict__\n                else:\n                    primary_model_dict[alias] = instance\n\n            merged_model_instance = merged_model_type(**primary_model_dict)\n            return merged_model_type, merged_model_alias, merged_model_instance\n        return primary_model_type, primary_model_alias, primary_model_instance\n\n    @staticmethod\n    def load_model_for_class(\n        trestle_root: pathlib.Path,\n        model_name: str,\n        model_class: TG,\n        file_content_type: Optional[FileContentType] = None\n    ) -> Tuple[TG, pathlib.Path]:\n\"\"\"Load a model by name and model class and infer file content type if not specified.\n\n        If you need to load an existing model but its content type may not be known, use this method.\n        But the file content type should be specified if it is somehow known.\n\n        Note:  This does not validate the model.  If you want to validate the model use the load_validate utilities.\n        \"\"\"\n        root_model_path = ModelUtils._root_path_for_top_level_model(\n            trestle_root, model_name, model_class\n        )  # type: ignore\n        if file_content_type is None:\n            file_content_type = FileContentType.path_to_content_type(root_model_path)\n        if not FileContentType.is_readable_file(file_content_type):\n            raise TrestleError(f'Unable to load model {model_name} without specifying json or yaml.')\n        full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n        _, _, model = ModelUtils.load_distributed(full_model_path, trestle_root)\n        return model, full_model_path  # type: ignore\n\n    @staticmethod\n    def load_model_for_type(trestle_root: pathlib.Path, model_type: str,\n                            model_name: str) -> Tuple[TopLevelOscalModel, pathlib.Path]:\n\"\"\"Load model for the given type and name.\"\"\"\n        dir_name = ModelUtils.model_type_to_model_dir(model_type)\n        model_path = trestle_root / dir_name / model_name\n\n        if not model_path.exists():\n            raise TrestleError(f'No model is found at path: {model_path}.')\n\n        _, _, oscal_object = ModelUtils.load_distributed(model_path, trestle_root)\n\n        return oscal_object, model_path  # type: ignore\n\n    @staticmethod\n    def save_top_level_model(\n        model: TopLevelOscalModel, trestle_root: pathlib.Path, model_name: str, file_content_type: FileContentType\n    ) -> None:\n\"\"\"Save a model by name and infer model type by inspection.\n\n        You don't need to specify the model type (catalog, profile, etc.) but you must specify the file content type.\n        If the model directory does not exist, it is created.\n        \"\"\"\n        root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model)\n        full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n        if not full_model_path.parent.exists():\n            full_model_path.parent.mkdir(parents=True, exist_ok=True)\n        model.oscal_write(full_model_path)\n\n    @staticmethod\n    def get_relative_model_type(relative_path: pathlib.Path) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n        Given the relative path of a file with respect to 'trestle_root' return the oscal model type.\n\n        Args:\n            relative_path: Relative path of the model with respect to the root directory of the trestle workspace.\n        Returns:\n            Type of Oscal Model for the provided model\n            Alias of that oscal model.\n        \"\"\"\n        if len(relative_path.parts) < 2:\n            raise TrestleError(\n                'Insufficient path length to be a valid relative path w.r.t trestle workspace root directory.'\n            )\n        model_dir = relative_path.parts[0]\n        model_relative_path = pathlib.Path(*relative_path.parts[2:])  # catalogs, profiles, etc\n\n        if model_dir in const.MODEL_DIR_LIST:\n            module_name = const.MODEL_DIR_TO_MODEL_MODULE[model_dir]\n        else:\n            raise TrestleError(f'No valid trestle model type directory (e.g. catalogs) found for {model_dir}.')\n\n        model_type, model_alias = ModelUtils.get_root_model(module_name)\n        full_alias = model_alias\n\n        for index, part in enumerate(model_relative_path.parts):\n            alias = ModelUtils._extract_alias(part)\n            if index > 0 or model_alias != alias:\n                model_alias = alias\n                full_alias = f'{full_alias}.{model_alias}'\n                if utils.is_collection_field_type(model_type):\n                    model_type = utils.get_inner_type(model_type)\n                else:\n                    model_type = model_type.alias_to_field_map()[alias].outer_type_\n\n        return model_type, full_alias\n\n    @staticmethod\n    def get_stripped_model_type(\n        absolute_path: pathlib.Path,\n        absolute_trestle_root: pathlib.Path,\n        aliases_not_to_be_stripped: List[str] = None\n    ) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n        Get the stripped contextual model class and alias based on the contextual path.\n\n        This function relies on the directory structure of the trestle model being edited to determine, based on the\n        existing files and folder, which fields should be stripped from the model type represented by the\n        path passed in as a parameter.\n        \"\"\"\n        if aliases_not_to_be_stripped is None:\n            aliases_not_to_be_stripped = []\n        singular_model_type, model_alias = ModelUtils.get_relative_model_type(\n            absolute_path.relative_to(absolute_trestle_root))\n        logger.debug(f'singular model type {singular_model_type} model alias {model_alias}')\n\n        # Stripped models do not apply to collection types such as List[] and Dict{}\n        # if model type is a list or dict, generate a new wrapping model for it\n        if utils.is_collection_field_type(singular_model_type):\n            malias = model_alias.split('.')[-1]\n            class_name = alias_to_classname(malias, AliasMode.JSON)\n            logger.debug(f'collection field type class name {class_name} and alias {malias}')\n            model_type = create_model(class_name, __base__=OscalBaseModel, __root__=(singular_model_type, ...))\n            logger.debug(f'model_type created: {model_type}')\n            return model_type, model_alias\n\n        malias = model_alias.split('.')[-1]\n        logger.debug(f'not collection field type, malias: {malias}')\n        if absolute_path.is_dir() and malias != ModelUtils._extract_alias(absolute_path.name):\n            split_subdir = absolute_path / malias\n        else:\n            split_subdir = absolute_path.parent / absolute_path.with_suffix('').name\n\n        aliases_to_be_stripped = set()\n        if split_subdir.exists():\n            for f in iterdir_without_hidden_files(split_subdir):\n                alias = ModelUtils._extract_alias(f.name)\n                if alias not in aliases_not_to_be_stripped:\n                    aliases_to_be_stripped.add(alias)\n\n        logger.debug(f'aliases to be stripped: {aliases_to_be_stripped}')\n        if len(aliases_to_be_stripped) > 0:\n            model_type = singular_model_type.create_stripped_model_type(\n                stripped_fields_aliases=list(aliases_to_be_stripped)\n            )\n            logger.debug(f'model_type: {model_type}')\n            return model_type, model_alias\n        return singular_model_type, model_alias\n\n    @staticmethod\n    def model_type_to_model_dir(model_type: str) -> str:\n\"\"\"Get plural model directory from model type.\"\"\"\n        if model_type not in const.MODEL_TYPE_LIST:\n            raise err.TrestleError(f'Not a valid model type: {model_type}.')\n        return const.MODEL_TYPE_TO_MODEL_DIR[model_type]\n\n    @staticmethod\n    def get_models_of_type(model_type: str, root: pathlib.Path) -> List[str]:\n\"\"\"Get list of model names for requested type in trestle directory.\"\"\"\n        if model_type not in const.MODEL_TYPE_LIST:\n            raise err.TrestleError(f'Model type {model_type} is not supported')\n        # search relative to project root\n        trestle_root = extract_trestle_project_root(root)\n        if not trestle_root:\n            logger.error(f'Given directory {root} is not within a trestle project.')\n            raise err.TrestleError('Given directory is not within a trestle project.')\n\n        # contruct path to the model file name\n        model_dir_name = ModelUtils.model_type_to_model_dir(model_type)\n        root_model_dir = trestle_root / model_dir_name\n        model_list = []\n        for f in root_model_dir.glob('*/'):\n            # only look for proper json and yaml files\n            if not ModelUtils._should_ignore(f.stem):\n                if not f.is_dir():\n                    logger.warning(\n                        f'Ignoring validation of misplaced file {f.name} '\n                        + f'found in the model directory, {model_dir_name}.'\n                    )\n                else:\n                    model_list.append(f.stem)\n        return model_list\n\n    @staticmethod\n    def get_all_models(root: pathlib.Path) -> List[Tuple[str, str]]:\n\"\"\"Get list of all models in trestle directory as tuples (model_type, model_name).\"\"\"\n        full_list = []\n        for model_type in const.MODEL_TYPE_LIST:\n            models = ModelUtils.get_models_of_type(model_type, root)\n            for m in models:\n                full_list.append((model_type, m))\n        return full_list\n\n    @staticmethod\n    def get_model_path_for_name_and_class(\n        trestle_root: pathlib.Path,\n        model_name: str,\n        model_class: Type[TopLevelOscalModel],\n        file_content_type: Optional[FileContentType] = None\n    ) -> Optional[pathlib.Path]:\n\"\"\"\n        Find the full path of a model given its name, model type and file content type.\n\n        If file_content_type is given it will not inspect the file system or confirm the needed path and file exists.\n        \"\"\"\n        if file_content_type is None:\n            root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n            file_content_type = FileContentType.path_to_content_type(root_model_path)\n            if not FileContentType.is_readable_file(file_content_type):\n                return None\n\n            return root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n\n        root_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n        return root_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n\n    @staticmethod\n    def get_singular_alias(alias_path: str, relative_path: Optional[pathlib.Path] = None) -> str:\n\"\"\"\n        Get the alias in the singular form from a jsonpath.\n\n        If contextual_mode is True and contextual_path is None, it assumes alias_path\n        is relative to the directory the user is running trestle from.\n\n        Args:\n            alias_path: The current alias element path as a string\n            relative_path: Optional relative path (w.r.t. trestle_root) to cater for relative element paths.\n        Returns:\n            Alias as a string\n        \"\"\"\n        if len(alias_path.strip()) == 0:\n            raise err.TrestleError(f'Invalid jsonpath {alias_path}')\n\n        singular_alias: str = ''\n\n        full_alias_path = alias_path\n        if relative_path:\n            logger.debug(f'get_singular_alias contextual mode: {str}')\n            _, full_model_alias = ModelUtils.get_relative_model_type(relative_path)\n            first_alias_a = full_model_alias.split('.')[-1]\n            first_alias_b = alias_path.split('.')[0]\n            if first_alias_a == first_alias_b:\n                full_model_alias = '.'.join(full_model_alias.split('.')[:-1])\n            full_alias_path = '.'.join([full_model_alias, alias_path]).strip('.')\n\n        path_parts = full_alias_path.split(const.ALIAS_PATH_SEPARATOR)\n        logger.debug(f'path parts: {path_parts}')\n\n        model_types = []\n\n        root_model_alias = path_parts[0]\n        found = False\n        for module_name in const.MODEL_TYPE_TO_MODEL_MODULE.values():\n            model_type, model_alias = ModelUtils.get_root_model(module_name)\n            if root_model_alias == model_alias:\n                found = True\n                model_types.append(model_type)\n                break\n\n        if not found:\n            raise err.TrestleError(f'{root_model_alias} is an invalid root model alias.')\n\n        if len(path_parts) == 1:\n            return root_model_alias\n\n        model_type = model_types[0]\n        # go through path parts skipping first one\n        for i in range(1, len(path_parts)):\n            if utils.is_collection_field_type(model_type):\n                # if it is a collection type and last part is * then break\n                if i == len(path_parts) - 1 and path_parts[i] == '*':\n                    break\n                # otherwise get the inner type of items in the collection\n                model_type = utils.get_inner_type(model_type)\n                # and bump i\n                i = i + 1\n            else:\n                path_part = path_parts[i]\n                field_map = model_type.alias_to_field_map()\n                if path_part not in field_map:\n                    continue\n                field = field_map[path_part]\n                model_type = field.outer_type_\n            model_types.append(model_type)\n\n        last_alias = path_parts[-1]\n        if last_alias == '*':\n            last_alias = path_parts[-2]\n\n        # generic model and not list, so return itself fixme doc\n        if not utils.is_collection_field_type(model_type):\n            return last_alias\n\n        parent_model_type = model_types[-2]\n        try:\n            field_map = parent_model_type.alias_to_field_map()\n            field = field_map[last_alias]\n            outer_type = field.outer_type_\n            inner_type = utils.get_inner_type(outer_type)\n            inner_type_name = inner_type.__name__\n            singular_alias = str_utils.classname_to_alias(inner_type_name, AliasMode.JSON)\n        except Exception as e:\n            raise err.TrestleError(f'Error in json path {alias_path}: {e}')\n\n        return singular_alias\n\n    @staticmethod\n    def get_root_model(module_name: str) -> Tuple[Type[Any], str]:\n\"\"\"Get the root model class and alias based on the module.\"\"\"\n        try:\n            module = importlib.import_module(module_name)\n        except ModuleNotFoundError as e:\n            raise err.TrestleError(str(e))\n\n        if hasattr(module, 'Model'):\n            model_metadata = next(iter(module.Model.__fields__.values()))\n            return model_metadata.type_, model_metadata.alias\n        raise err.TrestleError('Invalid module')\n\n    @staticmethod\n    def _root_path_for_top_level_model(\n        trestle_root: pathlib.Path, model_name: str, model_class: Union[TopLevelOscalModel, Type[TopLevelOscalModel]]\n    ) -> pathlib.Path:\n\"\"\"\n        Find the root path to a model given its name and class - with no suffix.\n\n        This is a private method used only to construct the root filepath based on model name and type.\n        It does not check for existence or content type and it does not create the directory if it does not exist.\n        \"\"\"\n        if not hasattr(model_class, '__module__') or model_class.__module__ not in const.MODEL_MODULE_LIST:\n            raise TrestleError(f'Unable to determine model type for model {model_name} with class {model_class}')\n        model_alias = const.MODEL_MODULE_TO_MODEL_TYPE[model_class.__module__]\n        model_dir = trestle_root / f'{const.MODEL_TYPE_TO_MODEL_DIR[model_alias]}/{model_name}'\n        return model_dir / model_alias\n\n    @staticmethod\n    def _extract_alias(string_dir: str) -> str:\n\"\"\"\n        Extract alias from filename or directory name removing extensions and prefixes related to dict and list.\n\n        As we need to do this for multiple parts of a path operating on strings is easier.\n        \"\"\"\n        alias = string_dir.split('.')[0].split(\n            const.IDX_SEP\n        )[-1]  # get suffix of file or directory name representing list or dict item\n        return alias\n\n    @staticmethod\n    def _should_ignore(name: str) -> bool:\n\"\"\"Check if the file or directory should be ignored or not.\"\"\"\n        return name[0] == '.' or name[0] == '_'\n\n    @staticmethod\n    def _load_list(abs_path: Path, abs_trestle_root: Path) -> Tuple[Type[OscalBaseModel], str, List[OscalBaseModel]]:\n\"\"\"Given path to a directory of list(array) models, load the distributed models.\"\"\"\n        aliases_not_to_be_stripped = []\n        instances_to_be_merged: List[OscalBaseModel] = []\n        collection_model_type, collection_model_alias = ModelUtils.get_stripped_model_type(abs_path, abs_trestle_root)\n        for path in sorted(trestle.common.file_utils.iterdir_without_hidden_files(abs_path)):\n\n            # ASSUMPTION HERE: if it is a directory, there's a file that can not be decomposed further.\n            if path.is_dir():\n                continue\n            _, model_alias, model_instance = ModelUtils.load_distributed(path, abs_trestle_root)\n\n            instances_to_be_merged.append(model_instance)\n            aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n\n        return collection_model_type, collection_model_alias, instances_to_be_merged\n\n    @staticmethod\n    def _parameter_to_dict_recurse(obj: Union[OscalBaseModel, str], partial: bool) -> Union[str, Dict[str, Any]]:\n\"\"\"\n        Convert obj to dict containing only string values with recursion.\n\n        Args:\n            obj: The parameter or its consituent parts in recursive calls\n            partial: Whether to convert the entire param or just the parts needed for markdown header\n\n        Returns:\n            The converted parameter as dictionary\n        \"\"\"\n        main_fields = ['id', 'label', 'values', 'select', 'choice', 'how_many', 'guidelines', 'prose']\n        if isinstance(obj, common.Remarks):\n            return obj.__root__\n        if isinstance(obj, common.HowMany):\n            return obj.value\n        # it is either a string already or we cast it to string\n        if not hasattr(obj, const.FIELDS_SET):\n            return str(obj)\n        # it is an oscal object and we need to recurse within its attributes\n        res = {}\n        for field in obj.__fields_set__:\n            if partial and field not in main_fields:\n                continue\n            attr = getattr(obj, field)\n            if not attr:\n                continue\n            if isinstance(attr, list):\n                new_list = []\n                for item in attr:\n                    new_list.append(ModelUtils._parameter_to_dict_recurse(item, partial))\n                res[field] = new_list\n            elif isinstance(attr, str):\n                res[field] = attr\n            else:\n                res[field] = ModelUtils._parameter_to_dict_recurse(attr, partial)\n        return res\n\n    @staticmethod\n    def parameter_to_dict(obj: Union[OscalBaseModel, str], partial: bool) -> Union[str, Dict[str, Any]]:\n\"\"\"\n        Convert obj to dict containing only string values, storing only the fields that have values set.\n\n        Args:\n            obj: The parameter or its consituent parts in recursive calls\n            partial: Whether to convert the entire param or just the parts needed for markdown header\n\n        Returns:\n            The converted parameter as dictionary, with values as None if not present\n        \"\"\"\n        res = ModelUtils._parameter_to_dict_recurse(obj, partial)\n        if 'values' not in res:\n            res['values'] = None  # type: ignore\n        return res\n\n    @staticmethod\n    def _string_to_howmany(count_str: str) -> Optional[str]:\n        clean_str = count_str.lower().strip().replace('-', ' ').replace('_', ' ')\n        if clean_str == const.ONE:\n            return common.HowMany.one  # type: ignore\n        if clean_str == const.ONE_OR_MORE_SPACED:\n            return common.HowMany.one_or_more  # type: ignore\n        return None\n\n    @staticmethod\n    def dict_to_parameter(param_dict: Dict[str, Any]) -> common.Parameter:\n\"\"\"\n        Convert dict with only string values to Parameter with handling for HowMany and with validity checks.\n\n        Args:\n            param_dict: Dictionary of pure string values representing Parameter contents\n\n        Returns:\n            A valid OSCAL Parameter\n\n        Notes:\n            This handles both partial and full parameter dictionaries\n            It checks for validity of the values if a select and HowMany is specified\n            There is special handling for values: If it is a single string it is converted to list of one ParameterValue\n            But if it is a list of strings is regarded as a list of values and is converted to a list of ParameterValues\n        \"\"\"\n        values = param_dict.get('values', [])\n        # special handling when only one value present - convert to list of 1\n        if isinstance(values, str):\n            values = [values]\n            param_dict['values'] = values\n        if 'select' in param_dict and 'how_many' in param_dict['select']:\n            count_str = param_dict['select']['how_many']\n            how_many = ModelUtils._string_to_howmany(count_str)\n            if how_many is None:\n                raise TrestleError(f'Unrecognized HowMany value {how_many} in Parameter: should be one-or-more or one.')\n            param_dict['select']['how_many'] = how_many\n            if how_many == const.ONE and len(values) > 1:\n                logger.warning(f'Parameter specifies HowMany=1 but has {len(values)} values given.')\n            choices = param_dict['select'].get('choice', [])\n            if choices and values:\n                for value in values:\n                    if value not in choices:\n                        logger.warning(f\"Parameter {param_dict['id']} has value \\\"{value}\\\" not in choices: {choices}.\")\n        props = param_dict.get('props', [])\n        if const.DISPLAY_NAME in param_dict:\n            display_name = param_dict.pop(const.DISPLAY_NAME)\n            props.append(common.Property(name=const.DISPLAY_NAME, value=display_name, ns=const.TRESTLE_GENERIC_NS))\n        if const.AGGREGATES in param_dict:\n            # removing aggregates as this is prop just informative in markdown\n            param_dict.pop(const.AGGREGATES)\n        param_value_origin = None\n        if const.PARAM_VALUE_ORIGIN in param_dict:\n            param_value_origin = param_dict.pop(const.PARAM_VALUE_ORIGIN)\n            if param_value_origin is not None:\n                props.append(common.Property(name=const.PARAM_VALUE_ORIGIN, value=param_value_origin))\n            else:\n                raise TrestleError(\n                    f'Parameter value origin property for parameter {param_dict[\"id\"]}'\n                    'is None and it should have a value'\n                )\n        if const.ALT_IDENTIFIER in param_dict:\n            # removing alt-identifier as this is prop just informative in markdown\n            param_dict.pop(const.ALT_IDENTIFIER)\n\n        if 'ns' in param_dict:\n            param_dict.pop('ns')\n        param = common.Parameter(**param_dict)\n        param.props = none_if_empty(props)\n        return param\n\n    @staticmethod\n    def last_modified_at_time(timestamp: Optional[datetime] = None) -> datetime:\n\"\"\"Generate a LastModified set to timestamp or now.\"\"\"\n        timestamp = timestamp if timestamp else datetime.now().astimezone()\n        return timestamp\n\n    @staticmethod\n    def update_last_modified(model: TopLevelOscalModel, timestamp: Optional[datetime] = None) -> None:\n\"\"\"Update the LastModified timestamp in top level model to now.\"\"\"\n        timestamp = timestamp if timestamp else datetime.now().astimezone()\n        model.metadata.last_modified = timestamp\n\n    @staticmethod\n    def model_age(model: TopLevelOscalModel) -> int:\n\"\"\"Find time in seconds since LastModified timestamp.\"\"\"\n        # default to one year if no last_modified\n        age_seconds = const.DAY_SECONDS * 365\n        if model.metadata.last_modified:\n            dt = datetime.now().astimezone() - model.metadata.last_modified\n            age_seconds = dt.seconds\n        return age_seconds\n\n    @staticmethod\n    def find_values_by_name(object_of_interest: Any, name_of_interest: str) -> List[Any]:\n\"\"\"Traverse object and return list of values of specified name.\"\"\"\n        loe = []\n        if isinstance(object_of_interest, BaseModel):\n            value = getattr(object_of_interest, name_of_interest, None)\n            if value is not None:\n                loe.append(value)\n            fields = getattr(object_of_interest, const.FIELDS_SET, None)\n            if fields is not None:\n                for field in fields:\n                    loe.extend(\n                        ModelUtils.find_values_by_name(getattr(object_of_interest, field, None), name_of_interest)\n                    )\n        elif type(object_of_interest) is list:\n            for item in object_of_interest:\n                loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n        elif type(object_of_interest) is dict:\n            if name_of_interest in object_of_interest:\n                loe.append(object_of_interest[name_of_interest])\n            for item in object_of_interest.values():\n                loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n        return loe\n\n    @staticmethod\n    def has_no_duplicate_values_by_name(object_of_interest: BaseModel, name_of_interest: str) -> bool:\n\"\"\"Determine if duplicate values of type exist in object.\"\"\"\n        loe = ModelUtils.find_values_by_name(object_of_interest, name_of_interest)\n        set_loe = set(loe)\n        if len(loe) == len(set_loe):\n            return True\n        items: Dict[str, Any] = {}\n        for item in loe:\n            items[item] = items.get(item, 0) + 1\n        # now print items\n        for item, instances in items.items():\n            if instances > 1:\n                logger.warning(f'Duplicate detected of item {item} with {instances} instances.')\n        return False\n\n    @staticmethod\n    def find_uuid_refs(object_of_interest: BaseModel) -> Set[str]:\n\"\"\"Find uuid references made in prose and links.\"\"\"\n        # hrefs have form #foo or #uuid\n        uuid_strs = ModelUtils.find_values_by_name(object_of_interest, 'href')\n\n        # prose has uuid refs in markdown form: [foo](#bar) or [foo](#uuid)\n        prose_list = ModelUtils.find_values_by_name(object_of_interest, 'prose')\n        for prose in prose_list:\n            matches = re.findall(const.MARKDOWN_URL_REGEX, prose)\n            # the [1] is to extract the inner of 3 capture patterns\n            new_uuids = [match[1] for match in matches]\n            uuid_strs.extend(new_uuids)\n\n        # collect the strings that start with # and are potential uuids\n        uuid_strs = [uuid_str for uuid_str in uuid_strs if uuid_str and uuid_str[0] == '#']\n\n        # go through all matches and build set of those that are uuids\n        uuid_set = {uuid_match for uuid_str in uuid_strs for uuid_match in re.findall(const.UUID_REGEX, uuid_str[1:])}\n        return uuid_set\n\n    @staticmethod\n    def _regenerate_uuids_in_place(object_of_interest: Any, uuid_lut: Dict[str, str]) -> Tuple[Any, Dict[str, str]]:\n\"\"\"Update all uuids in model that require updating.\n\n        Go through the model and replace all dicts with key == 'uuid' and replace the value with a new uuid4.\n        Build a lookup table of the updates that were made.\n        This function does not update the corresponding refs to those uuid's.  That is done by update_uuid_refs\n        Note that this function needs to be started off with uuid_lut == {}, i.e. an empty dict.\n        After that it recurses and grows the lut.\n\n        Args:\n            object_of_interest: pydantic.BaseModel, list, dict or str will be updated\n            uuid_lut: dict of the growing lut of old:new uuid's.  First call must be made with value {}\n\n        Returns:\n            The updated object_of_interest with new uuid's (but refs to them are not updated)\n            The final lookup table of old:new uuid's\n\n        \"\"\"\n        uuid_str = 'uuid'\n        # Certain types are known not to need updating and should not change\n        # Resources are identified by uuid, and the corresponding href will have # in front of the uuid string\n        # Neither of these should change\n        # If other similar types are found they should be added to the FixedUuidModel typevar to prevent updating\n        if isinstance(object_of_interest, common.Resource):\n            pass\n        elif isinstance(object_of_interest, BaseModel):\n            # fields has names of all fields in model\n            fields = getattr(object_of_interest, const.FIELDS_SET, None)\n            for field in fields:\n                new_object = None\n                if field == uuid_str:\n                    orig_uuid = getattr(object_of_interest, field)\n                    if orig_uuid:\n                        new_object = str(uuid.uuid4())\n                        uuid_lut[orig_uuid] = new_object\n                else:\n                    new_object, uuid_lut = ModelUtils._regenerate_uuids_in_place(\n                        object_of_interest.__dict__[field],\n                        uuid_lut\n                    )\n                object_of_interest.__dict__[field] = new_object\n        elif type(object_of_interest) is list:\n            new_list = []\n            for item in object_of_interest:\n                new_item, uuid_lut = ModelUtils._regenerate_uuids_in_place(item, uuid_lut)\n                new_list.append(new_item)\n            object_of_interest = new_list\n        elif type(object_of_interest) is dict:\n            new_dict = {}\n            for key, value in object_of_interest.items():\n                if key == uuid_str:\n                    new_val = str(uuid.uuid4())\n                    new_dict[uuid_str] = new_val\n                    uuid_lut[value] = new_val\n                else:\n                    new_value, uuid_lut = ModelUtils._regenerate_uuids_in_place(value, uuid_lut)\n                    new_dict[key] = new_value\n            object_of_interest = new_dict\n        return object_of_interest, uuid_lut\n\n    @staticmethod\n    def _update_new_uuid_refs(object_of_interest: Any, uuid_lut: Dict[str, str]) -> Tuple[Any, int]:\n\"\"\"Update all refs to uuids that were changed.\"\"\"\n        n_refs_updated = 0\n        if isinstance(object_of_interest, BaseModel):\n            fields = getattr(object_of_interest, const.FIELDS_SET, None)\n            for field in fields:\n                new_object, n_new_updates = ModelUtils._update_new_uuid_refs(\n                    object_of_interest.__dict__[field],\n                    uuid_lut\n                )\n                n_refs_updated += n_new_updates\n                object_of_interest.__dict__[field] = new_object\n        elif type(object_of_interest) is list:\n            new_list = []\n            for item in object_of_interest:\n                new_item, n_new_updates = ModelUtils._update_new_uuid_refs(item, uuid_lut)\n                n_refs_updated += n_new_updates\n                new_list.append(new_item)\n            object_of_interest = new_list\n        elif type(object_of_interest) is dict:\n            new_dict = {}\n            for key, value in object_of_interest.items():\n                if isinstance(value, str):\n                    if value in uuid_lut:\n                        new_dict[key] = uuid_lut[value]\n                        n_refs_updated += 1\n                    else:\n                        new_dict[key] = value\n                else:\n                    new_value, n_new_updates = ModelUtils._update_new_uuid_refs(value, uuid_lut)\n                    n_refs_updated += n_new_updates\n                    new_dict[key] = new_value\n            object_of_interest = new_dict\n        elif isinstance(object_of_interest, str):\n            if object_of_interest in uuid_lut:\n                n_refs_updated += 1\n                object_of_interest = uuid_lut[object_of_interest]\n        return object_of_interest, n_refs_updated\n\n    @staticmethod\n    def regenerate_uuids(object_of_interest: Any) -> Tuple[Any, Dict[str, str], int]:\n\"\"\"Regenerate all uuids in object and update corresponding references.\n\n        Find all dicts with key == 'uuid' and replace the value with a new uuid4.\n        Build a corresponding lookup table as you go, of old:new uuid values.\n        Then make a second pass through the object and replace all string values\n        present in the lookup table with the new value.\n\n        Args:\n            object_of_interest: pydantic.BaseModel, list, dict or str will be updated\n\n        Returns:\n            The updated object with new uuid's and refs\n            The final lookup table of old:new uuid's\n            A count of the number of refs that were updated\n        \"\"\"\n        new_object, uuid_lut = ModelUtils._regenerate_uuids_in_place(object_of_interest, {})\n        new_object, n_refs_updated = ModelUtils._update_new_uuid_refs(new_object, uuid_lut)\n        return new_object, uuid_lut, n_refs_updated\n\n    @staticmethod\n    def fields_set_non_none(obj: BaseModel) -> Set[str]:\n\"\"\"Find the fields set with Nones and empty items removed.\"\"\"\n        return set(as_filtered_list(list(obj.__fields_set__), lambda f: getattr(obj, f)))\n\n    @staticmethod\n    def _objects_differ(\n        obj_a: Any, obj_b: Any, ignore_type_list: List[Any], ignore_name_list: List[str], ignore_all_uuid: bool\n    ) -> bool:\n\"\"\"\n        Compare two objects with option to ignore given types.\n\n        This does not check for tuples or other structures that won't be found in JSON.\n        \"\"\"\n        obj_a_type = type(obj_a)\n        obj_b_type = type(obj_b)\n        if bool(obj_a) != bool(obj_b) or obj_a_type != obj_b_type:\n            return True\n        if not bool(obj_a):\n            return False\n        if obj_a_type in ignore_type_list:\n            return False\n        if obj_a_type is str:\n            return obj_a != obj_b\n        elif isinstance(obj_a, BaseModel):\n            fields_a = ModelUtils.fields_set_non_none(obj_a)\n            fields_b = ModelUtils.fields_set_non_none(obj_b)\n            if fields_a != fields_b:\n                return True\n            for field in list_utils.as_filtered_list(fields_a, lambda f: f not in ignore_name_list):  # type: ignore\n                if ignore_all_uuid and 'uuid' in field:\n                    continue\n                if ModelUtils._objects_differ(getattr(obj_a, field),\n                                              getattr(obj_b, field),\n                                              ignore_type_list,\n                                              ignore_name_list,\n                                              ignore_all_uuid):\n                    return True\n        elif obj_a_type is list:\n            if len(obj_a) != len(obj_b):\n                return True\n            for item_a, item_b in zip(obj_a, obj_b):\n                if ModelUtils._objects_differ(item_a, item_b, ignore_type_list, ignore_name_list, ignore_all_uuid):\n                    return True\n        elif obj_a_type is dict:\n            if obj_a.keys() != obj_b.keys():\n                return True\n            for key, val in obj_a.items():\n                if ignore_all_uuid and 'uuid' in key:\n                    continue\n                if key not in ignore_name_list and ModelUtils._objects_differ(\n                        val, obj_b[key], ignore_type_list, ignore_name_list, ignore_all_uuid):\n                    return True\n        elif obj_a != obj_b:\n            return True\n        return False\n\n    @staticmethod\n    def models_are_equivalent(\n        model_a: Optional[TopLevelOscalModel],\n        model_b: Optional[TopLevelOscalModel],\n        ignore_all_uuid: bool = False\n    ) -> bool:\n\"\"\"\n        Test if models are equivalent except for last modified and possibly uuid.\n\n        If a model has had uuids regenerated, then all uuids *and references to them* are updated.  This means that\n        special handling is required if a model has had uuids regenerated - when checking equivalence.\n        \"\"\"\n        uuid_type_list = [\n            common.LastModified,\n            common.LocationUuid,\n            common.PartyUuid,\n            common.RelatedRisk,\n            common.Source,\n            assessment_plan.RelatedObservation,\n            assessment_results.RelatedObservation,\n            poam.RelatedObservation,\n            poam.RelatedObservation1\n        ]\n        type_list = uuid_type_list if ignore_all_uuid else [common.LastModified]\n        return not ModelUtils._objects_differ(model_a, model_b, type_list, ['last_modified'], ignore_all_uuid)\n\n    @staticmethod\n    def get_title_from_model_uri(trestle_root: pathlib.Path, uri: str) -> str:\n\"\"\"Get title from model at uri.\"\"\"\n        try:\n            fetcher = cache.FetcherFactory.get_fetcher(trestle_root, uri)\n            model, _ = fetcher.get_oscal()\n            return model.metadata.title\n        except TrestleError as e:\n            logger.warning(f'Error finding title for model at uri {uri}: {e}')\n            raise\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils-methods","title":"Methods","text":""},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.dict_to_parameter","title":"dict_to_parameter(param_dict) staticmethod","text":"

                                                                            Convert dict with only string values to Parameter with handling for HowMany and with validity checks.

                                                                            Parameters:

                                                                            Name Type Description Default param_dict Dict[str, Any]

                                                                            Dictionary of pure string values representing Parameter contents

                                                                            required

                                                                            Returns:

                                                                            Type Description Parameter

                                                                            A valid OSCAL Parameter

                                                                            Notes

                                                                            This handles both partial and full parameter dictionaries It checks for validity of the values if a select and HowMany is specified There is special handling for values: If it is a single string it is converted to list of one ParameterValue But if it is a list of strings is regarded as a list of values and is converted to a list of ParameterValues

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef dict_to_parameter(param_dict: Dict[str, Any]) -> common.Parameter:\n\"\"\"\n    Convert dict with only string values to Parameter with handling for HowMany and with validity checks.\n\n    Args:\n        param_dict: Dictionary of pure string values representing Parameter contents\n\n    Returns:\n        A valid OSCAL Parameter\n\n    Notes:\n        This handles both partial and full parameter dictionaries\n        It checks for validity of the values if a select and HowMany is specified\n        There is special handling for values: If it is a single string it is converted to list of one ParameterValue\n        But if it is a list of strings is regarded as a list of values and is converted to a list of ParameterValues\n    \"\"\"\n    values = param_dict.get('values', [])\n    # special handling when only one value present - convert to list of 1\n    if isinstance(values, str):\n        values = [values]\n        param_dict['values'] = values\n    if 'select' in param_dict and 'how_many' in param_dict['select']:\n        count_str = param_dict['select']['how_many']\n        how_many = ModelUtils._string_to_howmany(count_str)\n        if how_many is None:\n            raise TrestleError(f'Unrecognized HowMany value {how_many} in Parameter: should be one-or-more or one.')\n        param_dict['select']['how_many'] = how_many\n        if how_many == const.ONE and len(values) > 1:\n            logger.warning(f'Parameter specifies HowMany=1 but has {len(values)} values given.')\n        choices = param_dict['select'].get('choice', [])\n        if choices and values:\n            for value in values:\n                if value not in choices:\n                    logger.warning(f\"Parameter {param_dict['id']} has value \\\"{value}\\\" not in choices: {choices}.\")\n    props = param_dict.get('props', [])\n    if const.DISPLAY_NAME in param_dict:\n        display_name = param_dict.pop(const.DISPLAY_NAME)\n        props.append(common.Property(name=const.DISPLAY_NAME, value=display_name, ns=const.TRESTLE_GENERIC_NS))\n    if const.AGGREGATES in param_dict:\n        # removing aggregates as this is prop just informative in markdown\n        param_dict.pop(const.AGGREGATES)\n    param_value_origin = None\n    if const.PARAM_VALUE_ORIGIN in param_dict:\n        param_value_origin = param_dict.pop(const.PARAM_VALUE_ORIGIN)\n        if param_value_origin is not None:\n            props.append(common.Property(name=const.PARAM_VALUE_ORIGIN, value=param_value_origin))\n        else:\n            raise TrestleError(\n                f'Parameter value origin property for parameter {param_dict[\"id\"]}'\n                'is None and it should have a value'\n            )\n    if const.ALT_IDENTIFIER in param_dict:\n        # removing alt-identifier as this is prop just informative in markdown\n        param_dict.pop(const.ALT_IDENTIFIER)\n\n    if 'ns' in param_dict:\n        param_dict.pop('ns')\n    param = common.Parameter(**param_dict)\n    param.props = none_if_empty(props)\n    return param\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.fields_set_non_none","title":"fields_set_non_none(obj) staticmethod","text":"

                                                                            Find the fields set with Nones and empty items removed.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef fields_set_non_none(obj: BaseModel) -> Set[str]:\n\"\"\"Find the fields set with Nones and empty items removed.\"\"\"\n    return set(as_filtered_list(list(obj.__fields_set__), lambda f: getattr(obj, f)))\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.find_uuid_refs","title":"find_uuid_refs(object_of_interest) staticmethod","text":"

                                                                            Find uuid references made in prose and links.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef find_uuid_refs(object_of_interest: BaseModel) -> Set[str]:\n\"\"\"Find uuid references made in prose and links.\"\"\"\n    # hrefs have form #foo or #uuid\n    uuid_strs = ModelUtils.find_values_by_name(object_of_interest, 'href')\n\n    # prose has uuid refs in markdown form: [foo](#bar) or [foo](#uuid)\n    prose_list = ModelUtils.find_values_by_name(object_of_interest, 'prose')\n    for prose in prose_list:\n        matches = re.findall(const.MARKDOWN_URL_REGEX, prose)\n        # the [1] is to extract the inner of 3 capture patterns\n        new_uuids = [match[1] for match in matches]\n        uuid_strs.extend(new_uuids)\n\n    # collect the strings that start with # and are potential uuids\n    uuid_strs = [uuid_str for uuid_str in uuid_strs if uuid_str and uuid_str[0] == '#']\n\n    # go through all matches and build set of those that are uuids\n    uuid_set = {uuid_match for uuid_str in uuid_strs for uuid_match in re.findall(const.UUID_REGEX, uuid_str[1:])}\n    return uuid_set\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.find_values_by_name","title":"find_values_by_name(object_of_interest, name_of_interest) staticmethod","text":"

                                                                            Traverse object and return list of values of specified name.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef find_values_by_name(object_of_interest: Any, name_of_interest: str) -> List[Any]:\n\"\"\"Traverse object and return list of values of specified name.\"\"\"\n    loe = []\n    if isinstance(object_of_interest, BaseModel):\n        value = getattr(object_of_interest, name_of_interest, None)\n        if value is not None:\n            loe.append(value)\n        fields = getattr(object_of_interest, const.FIELDS_SET, None)\n        if fields is not None:\n            for field in fields:\n                loe.extend(\n                    ModelUtils.find_values_by_name(getattr(object_of_interest, field, None), name_of_interest)\n                )\n    elif type(object_of_interest) is list:\n        for item in object_of_interest:\n            loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n    elif type(object_of_interest) is dict:\n        if name_of_interest in object_of_interest:\n            loe.append(object_of_interest[name_of_interest])\n        for item in object_of_interest.values():\n            loe.extend(ModelUtils.find_values_by_name(item, name_of_interest))\n    return loe\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_all_models","title":"get_all_models(root) staticmethod","text":"

                                                                            Get list of all models in trestle directory as tuples (model_type, model_name).

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_all_models(root: pathlib.Path) -> List[Tuple[str, str]]:\n\"\"\"Get list of all models in trestle directory as tuples (model_type, model_name).\"\"\"\n    full_list = []\n    for model_type in const.MODEL_TYPE_LIST:\n        models = ModelUtils.get_models_of_type(model_type, root)\n        for m in models:\n            full_list.append((model_type, m))\n    return full_list\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_model_path_for_name_and_class","title":"get_model_path_for_name_and_class(trestle_root, model_name, model_class, file_content_type=None) staticmethod","text":"

                                                                            Find the full path of a model given its name, model type and file content type.

                                                                            If file_content_type is given it will not inspect the file system or confirm the needed path and file exists.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_model_path_for_name_and_class(\n    trestle_root: pathlib.Path,\n    model_name: str,\n    model_class: Type[TopLevelOscalModel],\n    file_content_type: Optional[FileContentType] = None\n) -> Optional[pathlib.Path]:\n\"\"\"\n    Find the full path of a model given its name, model type and file content type.\n\n    If file_content_type is given it will not inspect the file system or confirm the needed path and file exists.\n    \"\"\"\n    if file_content_type is None:\n        root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n        file_content_type = FileContentType.path_to_content_type(root_model_path)\n        if not FileContentType.is_readable_file(file_content_type):\n            return None\n\n        return root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n\n    root_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model_class)\n    return root_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_models_of_type","title":"get_models_of_type(model_type, root) staticmethod","text":"

                                                                            Get list of model names for requested type in trestle directory.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_models_of_type(model_type: str, root: pathlib.Path) -> List[str]:\n\"\"\"Get list of model names for requested type in trestle directory.\"\"\"\n    if model_type not in const.MODEL_TYPE_LIST:\n        raise err.TrestleError(f'Model type {model_type} is not supported')\n    # search relative to project root\n    trestle_root = extract_trestle_project_root(root)\n    if not trestle_root:\n        logger.error(f'Given directory {root} is not within a trestle project.')\n        raise err.TrestleError('Given directory is not within a trestle project.')\n\n    # contruct path to the model file name\n    model_dir_name = ModelUtils.model_type_to_model_dir(model_type)\n    root_model_dir = trestle_root / model_dir_name\n    model_list = []\n    for f in root_model_dir.glob('*/'):\n        # only look for proper json and yaml files\n        if not ModelUtils._should_ignore(f.stem):\n            if not f.is_dir():\n                logger.warning(\n                    f'Ignoring validation of misplaced file {f.name} '\n                    + f'found in the model directory, {model_dir_name}.'\n                )\n            else:\n                model_list.append(f.stem)\n    return model_list\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_relative_model_type","title":"get_relative_model_type(relative_path) staticmethod","text":"

                                                                            Given the relative path of a file with respect to 'trestle_root' return the oscal model type.

                                                                            Parameters:

                                                                            Name Type Description Default relative_path Path

                                                                            Relative path of the model with respect to the root directory of the trestle workspace.

                                                                            required

                                                                            Returns:

                                                                            Type Description Tuple[Type[trestle.core.base_model.OscalBaseModel], str]

                                                                            Type of Oscal Model for the provided model Alias of that oscal model.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_relative_model_type(relative_path: pathlib.Path) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n    Given the relative path of a file with respect to 'trestle_root' return the oscal model type.\n\n    Args:\n        relative_path: Relative path of the model with respect to the root directory of the trestle workspace.\n    Returns:\n        Type of Oscal Model for the provided model\n        Alias of that oscal model.\n    \"\"\"\n    if len(relative_path.parts) < 2:\n        raise TrestleError(\n            'Insufficient path length to be a valid relative path w.r.t trestle workspace root directory.'\n        )\n    model_dir = relative_path.parts[0]\n    model_relative_path = pathlib.Path(*relative_path.parts[2:])  # catalogs, profiles, etc\n\n    if model_dir in const.MODEL_DIR_LIST:\n        module_name = const.MODEL_DIR_TO_MODEL_MODULE[model_dir]\n    else:\n        raise TrestleError(f'No valid trestle model type directory (e.g. catalogs) found for {model_dir}.')\n\n    model_type, model_alias = ModelUtils.get_root_model(module_name)\n    full_alias = model_alias\n\n    for index, part in enumerate(model_relative_path.parts):\n        alias = ModelUtils._extract_alias(part)\n        if index > 0 or model_alias != alias:\n            model_alias = alias\n            full_alias = f'{full_alias}.{model_alias}'\n            if utils.is_collection_field_type(model_type):\n                model_type = utils.get_inner_type(model_type)\n            else:\n                model_type = model_type.alias_to_field_map()[alias].outer_type_\n\n    return model_type, full_alias\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_root_model","title":"get_root_model(module_name) staticmethod","text":"

                                                                            Get the root model class and alias based on the module.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_root_model(module_name: str) -> Tuple[Type[Any], str]:\n\"\"\"Get the root model class and alias based on the module.\"\"\"\n    try:\n        module = importlib.import_module(module_name)\n    except ModuleNotFoundError as e:\n        raise err.TrestleError(str(e))\n\n    if hasattr(module, 'Model'):\n        model_metadata = next(iter(module.Model.__fields__.values()))\n        return model_metadata.type_, model_metadata.alias\n    raise err.TrestleError('Invalid module')\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_singular_alias","title":"get_singular_alias(alias_path, relative_path=None) staticmethod","text":"

                                                                            Get the alias in the singular form from a jsonpath.

                                                                            If contextual_mode is True and contextual_path is None, it assumes alias_path is relative to the directory the user is running trestle from.

                                                                            Parameters:

                                                                            Name Type Description Default alias_path str

                                                                            The current alias element path as a string

                                                                            required relative_path Optional[pathlib.Path]

                                                                            Optional relative path (w.r.t. trestle_root) to cater for relative element paths.

                                                                            None

                                                                            Returns:

                                                                            Type Description str

                                                                            Alias as a string

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_singular_alias(alias_path: str, relative_path: Optional[pathlib.Path] = None) -> str:\n\"\"\"\n    Get the alias in the singular form from a jsonpath.\n\n    If contextual_mode is True and contextual_path is None, it assumes alias_path\n    is relative to the directory the user is running trestle from.\n\n    Args:\n        alias_path: The current alias element path as a string\n        relative_path: Optional relative path (w.r.t. trestle_root) to cater for relative element paths.\n    Returns:\n        Alias as a string\n    \"\"\"\n    if len(alias_path.strip()) == 0:\n        raise err.TrestleError(f'Invalid jsonpath {alias_path}')\n\n    singular_alias: str = ''\n\n    full_alias_path = alias_path\n    if relative_path:\n        logger.debug(f'get_singular_alias contextual mode: {str}')\n        _, full_model_alias = ModelUtils.get_relative_model_type(relative_path)\n        first_alias_a = full_model_alias.split('.')[-1]\n        first_alias_b = alias_path.split('.')[0]\n        if first_alias_a == first_alias_b:\n            full_model_alias = '.'.join(full_model_alias.split('.')[:-1])\n        full_alias_path = '.'.join([full_model_alias, alias_path]).strip('.')\n\n    path_parts = full_alias_path.split(const.ALIAS_PATH_SEPARATOR)\n    logger.debug(f'path parts: {path_parts}')\n\n    model_types = []\n\n    root_model_alias = path_parts[0]\n    found = False\n    for module_name in const.MODEL_TYPE_TO_MODEL_MODULE.values():\n        model_type, model_alias = ModelUtils.get_root_model(module_name)\n        if root_model_alias == model_alias:\n            found = True\n            model_types.append(model_type)\n            break\n\n    if not found:\n        raise err.TrestleError(f'{root_model_alias} is an invalid root model alias.')\n\n    if len(path_parts) == 1:\n        return root_model_alias\n\n    model_type = model_types[0]\n    # go through path parts skipping first one\n    for i in range(1, len(path_parts)):\n        if utils.is_collection_field_type(model_type):\n            # if it is a collection type and last part is * then break\n            if i == len(path_parts) - 1 and path_parts[i] == '*':\n                break\n            # otherwise get the inner type of items in the collection\n            model_type = utils.get_inner_type(model_type)\n            # and bump i\n            i = i + 1\n        else:\n            path_part = path_parts[i]\n            field_map = model_type.alias_to_field_map()\n            if path_part not in field_map:\n                continue\n            field = field_map[path_part]\n            model_type = field.outer_type_\n        model_types.append(model_type)\n\n    last_alias = path_parts[-1]\n    if last_alias == '*':\n        last_alias = path_parts[-2]\n\n    # generic model and not list, so return itself fixme doc\n    if not utils.is_collection_field_type(model_type):\n        return last_alias\n\n    parent_model_type = model_types[-2]\n    try:\n        field_map = parent_model_type.alias_to_field_map()\n        field = field_map[last_alias]\n        outer_type = field.outer_type_\n        inner_type = utils.get_inner_type(outer_type)\n        inner_type_name = inner_type.__name__\n        singular_alias = str_utils.classname_to_alias(inner_type_name, AliasMode.JSON)\n    except Exception as e:\n        raise err.TrestleError(f'Error in json path {alias_path}: {e}')\n\n    return singular_alias\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_stripped_model_type","title":"get_stripped_model_type(absolute_path, absolute_trestle_root, aliases_not_to_be_stripped=None) staticmethod","text":"

                                                                            Get the stripped contextual model class and alias based on the contextual path.

                                                                            This function relies on the directory structure of the trestle model being edited to determine, based on the existing files and folder, which fields should be stripped from the model type represented by the path passed in as a parameter.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_stripped_model_type(\n    absolute_path: pathlib.Path,\n    absolute_trestle_root: pathlib.Path,\n    aliases_not_to_be_stripped: List[str] = None\n) -> Tuple[Type[OscalBaseModel], str]:\n\"\"\"\n    Get the stripped contextual model class and alias based on the contextual path.\n\n    This function relies on the directory structure of the trestle model being edited to determine, based on the\n    existing files and folder, which fields should be stripped from the model type represented by the\n    path passed in as a parameter.\n    \"\"\"\n    if aliases_not_to_be_stripped is None:\n        aliases_not_to_be_stripped = []\n    singular_model_type, model_alias = ModelUtils.get_relative_model_type(\n        absolute_path.relative_to(absolute_trestle_root))\n    logger.debug(f'singular model type {singular_model_type} model alias {model_alias}')\n\n    # Stripped models do not apply to collection types such as List[] and Dict{}\n    # if model type is a list or dict, generate a new wrapping model for it\n    if utils.is_collection_field_type(singular_model_type):\n        malias = model_alias.split('.')[-1]\n        class_name = alias_to_classname(malias, AliasMode.JSON)\n        logger.debug(f'collection field type class name {class_name} and alias {malias}')\n        model_type = create_model(class_name, __base__=OscalBaseModel, __root__=(singular_model_type, ...))\n        logger.debug(f'model_type created: {model_type}')\n        return model_type, model_alias\n\n    malias = model_alias.split('.')[-1]\n    logger.debug(f'not collection field type, malias: {malias}')\n    if absolute_path.is_dir() and malias != ModelUtils._extract_alias(absolute_path.name):\n        split_subdir = absolute_path / malias\n    else:\n        split_subdir = absolute_path.parent / absolute_path.with_suffix('').name\n\n    aliases_to_be_stripped = set()\n    if split_subdir.exists():\n        for f in iterdir_without_hidden_files(split_subdir):\n            alias = ModelUtils._extract_alias(f.name)\n            if alias not in aliases_not_to_be_stripped:\n                aliases_to_be_stripped.add(alias)\n\n    logger.debug(f'aliases to be stripped: {aliases_to_be_stripped}')\n    if len(aliases_to_be_stripped) > 0:\n        model_type = singular_model_type.create_stripped_model_type(\n            stripped_fields_aliases=list(aliases_to_be_stripped)\n        )\n        logger.debug(f'model_type: {model_type}')\n        return model_type, model_alias\n    return singular_model_type, model_alias\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.get_title_from_model_uri","title":"get_title_from_model_uri(trestle_root, uri) staticmethod","text":"

                                                                            Get title from model at uri.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef get_title_from_model_uri(trestle_root: pathlib.Path, uri: str) -> str:\n\"\"\"Get title from model at uri.\"\"\"\n    try:\n        fetcher = cache.FetcherFactory.get_fetcher(trestle_root, uri)\n        model, _ = fetcher.get_oscal()\n        return model.metadata.title\n    except TrestleError as e:\n        logger.warning(f'Error finding title for model at uri {uri}: {e}')\n        raise\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.has_no_duplicate_values_by_name","title":"has_no_duplicate_values_by_name(object_of_interest, name_of_interest) staticmethod","text":"

                                                                            Determine if duplicate values of type exist in object.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef has_no_duplicate_values_by_name(object_of_interest: BaseModel, name_of_interest: str) -> bool:\n\"\"\"Determine if duplicate values of type exist in object.\"\"\"\n    loe = ModelUtils.find_values_by_name(object_of_interest, name_of_interest)\n    set_loe = set(loe)\n    if len(loe) == len(set_loe):\n        return True\n    items: Dict[str, Any] = {}\n    for item in loe:\n        items[item] = items.get(item, 0) + 1\n    # now print items\n    for item, instances in items.items():\n        if instances > 1:\n            logger.warning(f'Duplicate detected of item {item} with {instances} instances.')\n    return False\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.last_modified_at_time","title":"last_modified_at_time(timestamp=None) staticmethod","text":"

                                                                            Generate a LastModified set to timestamp or now.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef last_modified_at_time(timestamp: Optional[datetime] = None) -> datetime:\n\"\"\"Generate a LastModified set to timestamp or now.\"\"\"\n    timestamp = timestamp if timestamp else datetime.now().astimezone()\n    return timestamp\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.load_distributed","title":"load_distributed(abs_path, abs_trestle_root, collection_type=None) staticmethod","text":"

                                                                            Given path to a model, load the model.

                                                                            If the model is decomposed/split/distributed,the decomposed models are loaded recursively.

                                                                            Parameters:

                                                                            Name Type Description Default abs_path Path

                                                                            The path to the file/directory to be loaded.

                                                                            required abs_trestle_root Path

                                                                            The trestle workspace root directory.

                                                                            required collection_type Optional[Type[Any]]

                                                                            The type of collection model, if it is a collection model. typing.List is the only collection type handled or expected. Defaults to None.

                                                                            None

                                                                            Returns:

                                                                            Type Description Tuple[Type[trestle.core.base_model.OscalBaseModel], str, Union[trestle.core.base_model.OscalBaseModel, List[trestle.core.base_model.OscalBaseModel], Dict[str, trestle.core.base_model.OscalBaseModel]]]

                                                                            Return a tuple of Model Type (e.g. class 'trestle.oscal.catalog.Catalog'), Model Alias (e.g. 'catalog.metadata') and Instance of the Model. If the model is decomposed/split/distributed, the instance of the model contains the decomposed models loaded recursively.

                                                                            Note

                                                                            This does not validate the model. You must either validate the model separately or use the load_validate utilities.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef load_distributed(\n    abs_path: Path,\n    abs_trestle_root: Path,\n    collection_type: Optional[Type[Any]] = None\n) -> Tuple[Type[OscalBaseModel],\n           str,\n           Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]]]:\n\"\"\"\n    Given path to a model, load the model.\n\n    If the model is decomposed/split/distributed,the decomposed models are loaded recursively.\n\n    Args:\n        abs_path: The path to the file/directory to be loaded.\n        abs_trestle_root: The trestle workspace root directory.\n        collection_type: The type of collection model, if it is a collection model.\n            typing.List is the only collection type handled or expected.\n            Defaults to None.\n\n    Returns:\n        Return a tuple of Model Type (e.g. class 'trestle.oscal.catalog.Catalog'),\n        Model Alias (e.g. 'catalog.metadata') and Instance of the Model.\n        If the model is decomposed/split/distributed, the instance of the model contains\n        the decomposed models loaded recursively.\n\n    Note:\n        This does not validate the model.  You must either validate the model separately or use the load_validate\n        utilities.\n    \"\"\"\n    # if trying to load file that does not exist, load path instead\n    if not abs_path.exists():\n        abs_path = abs_path.with_name(abs_path.stem)\n\n    if not abs_path.exists():\n        raise TrestleNotFoundError(f'File {abs_path} not found for load.')\n\n    if collection_type:\n        # If the path contains a list type model\n        if collection_type is list:\n            return ModelUtils._load_list(abs_path, abs_trestle_root)\n        # the only other collection type in OSCAL is dict, and it only applies to include_all,\n        # which is too granular ever to be loaded by this routine\n        else:\n            raise TrestleError(f'Collection type {collection_type} not recognized for distributed load.')\n\n    # Get current model\n    primary_model_type, primary_model_alias = ModelUtils.get_stripped_model_type(abs_path, abs_trestle_root)\n    primary_model_instance: Optional[Union[OscalBaseModel, List[OscalBaseModel], Dict[str, OscalBaseModel]]] = None\n\n    # is this an attempt to load an actual json or yaml file?\n    content_type = FileContentType.path_to_content_type(abs_path)\n    # if file is sought but it doesn't exist, ignore and load as decomposed model\n    if FileContentType.is_readable_file(content_type) and abs_path.exists():\n        primary_model_instance = primary_model_type.oscal_read(abs_path)\n    # Is model decomposed?\n    decomposed_dir = abs_path.with_name(abs_path.stem)\n\n    if decomposed_dir.exists():\n        aliases_not_to_be_stripped = []\n        instances_to_be_merged: List[OscalBaseModel] = []\n\n        for local_path in sorted(trestle.common.file_utils.iterdir_without_hidden_files(decomposed_dir)):\n            if local_path.is_file():\n                model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path, abs_trestle_root)\n                aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                instances_to_be_merged.append(model_instance)\n\n            elif local_path.is_dir():\n                model_type, model_alias = ModelUtils.get_stripped_model_type(local_path, abs_trestle_root)\n                # Only load the directory if it is a collection model. Otherwise do nothing - it gets loaded when\n                # iterating over the model file\n\n                # If a model is just a container for a list e.g.\n                # class Foo(OscalBaseModel):  noqa: E800\n                #      __root__: List[Bar]    noqa: E800\n                # You need to test whether first a root key exists\n                # then whether the outer_type of root is a collection.\n                # Alternative is to do a try except to avoid the error for an unknown key.\n\n                if model_type.is_collection_container():\n                    # This directory is a decomposed List or Dict\n                    collection_type = model_type.get_collection_type()\n                    model_type, model_alias, model_instance = ModelUtils.load_distributed(local_path,\n                                                                                          abs_trestle_root,\n                                                                                          collection_type)\n                    aliases_not_to_be_stripped.append(model_alias.split('.')[-1])\n                    instances_to_be_merged.append(model_instance)\n        primary_model_dict = {}\n        if primary_model_instance is not None:\n            primary_model_dict = primary_model_instance.__dict__\n\n        merged_model_type, merged_model_alias = ModelUtils.get_stripped_model_type(abs_path,\n                                                                                   abs_trestle_root,\n                                                                                   aliases_not_to_be_stripped)\n\n        # The following use of top_level is to allow loading of a top level model by name only, e.g. MyCatalog\n        # There may be a better overall way to approach this.\n        top_level = len(merged_model_alias.split('.')) == 1\n\n        for i in range(len(aliases_not_to_be_stripped)):\n            alias = aliases_not_to_be_stripped[i]\n            instance = instances_to_be_merged[i]\n            if hasattr(instance, '__dict__') and '__root__' in instance.__dict__ and isinstance(instance,\n                                                                                                OscalBaseModel):\n                instance = instance.__dict__['__root__']\n            if top_level and not primary_model_dict:\n                primary_model_dict = instance.__dict__\n            else:\n                primary_model_dict[alias] = instance\n\n        merged_model_instance = merged_model_type(**primary_model_dict)\n        return merged_model_type, merged_model_alias, merged_model_instance\n    return primary_model_type, primary_model_alias, primary_model_instance\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.load_model_for_class","title":"load_model_for_class(trestle_root, model_name, model_class, file_content_type=None) staticmethod","text":"

                                                                            Load a model by name and model class and infer file content type if not specified.

                                                                            If you need to load an existing model but its content type may not be known, use this method. But the file content type should be specified if it is somehow known.

                                                                            Note: This does not validate the model. If you want to validate the model use the load_validate utilities.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef load_model_for_class(\n    trestle_root: pathlib.Path,\n    model_name: str,\n    model_class: TG,\n    file_content_type: Optional[FileContentType] = None\n) -> Tuple[TG, pathlib.Path]:\n\"\"\"Load a model by name and model class and infer file content type if not specified.\n\n    If you need to load an existing model but its content type may not be known, use this method.\n    But the file content type should be specified if it is somehow known.\n\n    Note:  This does not validate the model.  If you want to validate the model use the load_validate utilities.\n    \"\"\"\n    root_model_path = ModelUtils._root_path_for_top_level_model(\n        trestle_root, model_name, model_class\n    )  # type: ignore\n    if file_content_type is None:\n        file_content_type = FileContentType.path_to_content_type(root_model_path)\n    if not FileContentType.is_readable_file(file_content_type):\n        raise TrestleError(f'Unable to load model {model_name} without specifying json or yaml.')\n    full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n    _, _, model = ModelUtils.load_distributed(full_model_path, trestle_root)\n    return model, full_model_path  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.load_model_for_type","title":"load_model_for_type(trestle_root, model_type, model_name) staticmethod","text":"

                                                                            Load model for the given type and name.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef load_model_for_type(trestle_root: pathlib.Path, model_type: str,\n                        model_name: str) -> Tuple[TopLevelOscalModel, pathlib.Path]:\n\"\"\"Load model for the given type and name.\"\"\"\n    dir_name = ModelUtils.model_type_to_model_dir(model_type)\n    model_path = trestle_root / dir_name / model_name\n\n    if not model_path.exists():\n        raise TrestleError(f'No model is found at path: {model_path}.')\n\n    _, _, oscal_object = ModelUtils.load_distributed(model_path, trestle_root)\n\n    return oscal_object, model_path  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.model_age","title":"model_age(model) staticmethod","text":"

                                                                            Find time in seconds since LastModified timestamp.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef model_age(model: TopLevelOscalModel) -> int:\n\"\"\"Find time in seconds since LastModified timestamp.\"\"\"\n    # default to one year if no last_modified\n    age_seconds = const.DAY_SECONDS * 365\n    if model.metadata.last_modified:\n        dt = datetime.now().astimezone() - model.metadata.last_modified\n        age_seconds = dt.seconds\n    return age_seconds\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.model_type_to_model_dir","title":"model_type_to_model_dir(model_type) staticmethod","text":"

                                                                            Get plural model directory from model type.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef model_type_to_model_dir(model_type: str) -> str:\n\"\"\"Get plural model directory from model type.\"\"\"\n    if model_type not in const.MODEL_TYPE_LIST:\n        raise err.TrestleError(f'Not a valid model type: {model_type}.')\n    return const.MODEL_TYPE_TO_MODEL_DIR[model_type]\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.models_are_equivalent","title":"models_are_equivalent(model_a, model_b, ignore_all_uuid=False) staticmethod","text":"

                                                                            Test if models are equivalent except for last modified and possibly uuid.

                                                                            If a model has had uuids regenerated, then all uuids and references to them are updated. This means that special handling is required if a model has had uuids regenerated - when checking equivalence.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef models_are_equivalent(\n    model_a: Optional[TopLevelOscalModel],\n    model_b: Optional[TopLevelOscalModel],\n    ignore_all_uuid: bool = False\n) -> bool:\n\"\"\"\n    Test if models are equivalent except for last modified and possibly uuid.\n\n    If a model has had uuids regenerated, then all uuids *and references to them* are updated.  This means that\n    special handling is required if a model has had uuids regenerated - when checking equivalence.\n    \"\"\"\n    uuid_type_list = [\n        common.LastModified,\n        common.LocationUuid,\n        common.PartyUuid,\n        common.RelatedRisk,\n        common.Source,\n        assessment_plan.RelatedObservation,\n        assessment_results.RelatedObservation,\n        poam.RelatedObservation,\n        poam.RelatedObservation1\n    ]\n    type_list = uuid_type_list if ignore_all_uuid else [common.LastModified]\n    return not ModelUtils._objects_differ(model_a, model_b, type_list, ['last_modified'], ignore_all_uuid)\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.parameter_to_dict","title":"parameter_to_dict(obj, partial) staticmethod","text":"

                                                                            Convert obj to dict containing only string values, storing only the fields that have values set.

                                                                            Parameters:

                                                                            Name Type Description Default obj Union[trestle.core.base_model.OscalBaseModel, str]

                                                                            The parameter or its consituent parts in recursive calls

                                                                            required partial bool

                                                                            Whether to convert the entire param or just the parts needed for markdown header

                                                                            required

                                                                            Returns:

                                                                            Type Description Union[str, Dict[str, Any]]

                                                                            The converted parameter as dictionary, with values as None if not present

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef parameter_to_dict(obj: Union[OscalBaseModel, str], partial: bool) -> Union[str, Dict[str, Any]]:\n\"\"\"\n    Convert obj to dict containing only string values, storing only the fields that have values set.\n\n    Args:\n        obj: The parameter or its consituent parts in recursive calls\n        partial: Whether to convert the entire param or just the parts needed for markdown header\n\n    Returns:\n        The converted parameter as dictionary, with values as None if not present\n    \"\"\"\n    res = ModelUtils._parameter_to_dict_recurse(obj, partial)\n    if 'values' not in res:\n        res['values'] = None  # type: ignore\n    return res\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.regenerate_uuids","title":"regenerate_uuids(object_of_interest) staticmethod","text":"

                                                                            Regenerate all uuids in object and update corresponding references.

                                                                            Find all dicts with key == 'uuid' and replace the value with a new uuid4. Build a corresponding lookup table as you go, of old:new uuid values. Then make a second pass through the object and replace all string values present in the lookup table with the new value.

                                                                            Parameters:

                                                                            Name Type Description Default object_of_interest Any

                                                                            pydantic.BaseModel, list, dict or str will be updated

                                                                            required

                                                                            Returns:

                                                                            Type Description The updated object with new uuid's and refs The final lookup table of old

                                                                            new uuid's A count of the number of refs that were updated

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef regenerate_uuids(object_of_interest: Any) -> Tuple[Any, Dict[str, str], int]:\n\"\"\"Regenerate all uuids in object and update corresponding references.\n\n    Find all dicts with key == 'uuid' and replace the value with a new uuid4.\n    Build a corresponding lookup table as you go, of old:new uuid values.\n    Then make a second pass through the object and replace all string values\n    present in the lookup table with the new value.\n\n    Args:\n        object_of_interest: pydantic.BaseModel, list, dict or str will be updated\n\n    Returns:\n        The updated object with new uuid's and refs\n        The final lookup table of old:new uuid's\n        A count of the number of refs that were updated\n    \"\"\"\n    new_object, uuid_lut = ModelUtils._regenerate_uuids_in_place(object_of_interest, {})\n    new_object, n_refs_updated = ModelUtils._update_new_uuid_refs(new_object, uuid_lut)\n    return new_object, uuid_lut, n_refs_updated\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.save_top_level_model","title":"save_top_level_model(model, trestle_root, model_name, file_content_type) staticmethod","text":"

                                                                            Save a model by name and infer model type by inspection.

                                                                            You don't need to specify the model type (catalog, profile, etc.) but you must specify the file content type. If the model directory does not exist, it is created.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef save_top_level_model(\n    model: TopLevelOscalModel, trestle_root: pathlib.Path, model_name: str, file_content_type: FileContentType\n) -> None:\n\"\"\"Save a model by name and infer model type by inspection.\n\n    You don't need to specify the model type (catalog, profile, etc.) but you must specify the file content type.\n    If the model directory does not exist, it is created.\n    \"\"\"\n    root_model_path = ModelUtils._root_path_for_top_level_model(trestle_root, model_name, model)\n    full_model_path = root_model_path.with_suffix(FileContentType.to_file_extension(file_content_type))\n    if not full_model_path.parent.exists():\n        full_model_path.parent.mkdir(parents=True, exist_ok=True)\n    model.oscal_write(full_model_path)\n
                                                                            "},{"location":"api_reference/trestle.common.model_utils/#trestle.common.model_utils.ModelUtils.update_last_modified","title":"update_last_modified(model, timestamp=None) staticmethod","text":"

                                                                            Update the LastModified timestamp in top level model to now.

                                                                            Source code in trestle/common/model_utils.py
                                                                            @staticmethod\ndef update_last_modified(model: TopLevelOscalModel, timestamp: Optional[datetime] = None) -> None:\n\"\"\"Update the LastModified timestamp in top level model to now.\"\"\"\n    timestamp = timestamp if timestamp else datetime.now().astimezone()\n    model.metadata.last_modified = timestamp\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/","title":"str_utils","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils","title":"trestle.common.str_utils","text":"

                                                                            Trestle String Utils.

                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils-classes","title":"Classes","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.AliasMode","title":" AliasMode (Enum) ","text":"

                                                                            Allowed formats for classname alias.

                                                                            Currently there are only two. If others are added, check they get handled properly in the code.

                                                                            Source code in trestle/common/str_utils.py
                                                                            class AliasMode(enum.Enum):\n\"\"\"\n    Allowed formats for classname alias.\n\n    Currently there are only two.  If others are added, check they get handled properly in the code.\n    \"\"\"\n\n    JSON = 1\n    FIELD = 2\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.AliasMode.FIELD","title":"FIELD","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.AliasMode.JSON","title":"JSON","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.alias_to_classname","title":"alias_to_classname(alias, mode)","text":"

                                                                            Return class name based dashed or snake alias.

                                                                            This is applicable creating dynamic wrapper model for a list or dict field.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def alias_to_classname(alias: str, mode: AliasMode) -> str:\n\"\"\"\n    Return class name based dashed or snake alias.\n\n    This is applicable creating dynamic wrapper model for a list or dict field.\n    \"\"\"\n    if mode == AliasMode.JSON:\n        return _snake_to_upper_camel(alias.replace('-', '_'))\n    return _snake_to_upper_camel(alias)\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.as_string","title":"as_string(string_or_none)","text":"

                                                                            Convert string or None to itself or empty string.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def as_string(string_or_none: Optional[str]) -> str:\n\"\"\"Convert string or None to itself or empty string.\"\"\"\n    return string_or_none if string_or_none else ''\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.classname_to_alias","title":"classname_to_alias(classname, mode)","text":"

                                                                            Return oscal key name or field element name based on class name.

                                                                            This is applicable when asking for a singular element.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def classname_to_alias(classname: str, mode: AliasMode) -> str:\n\"\"\"\n    Return oscal key name or field element name based on class name.\n\n    This is applicable when asking for a singular element.\n    \"\"\"\n    suffix = classname.split('.')[-1]\n\n    # the alias mode is either json or field - yaml doesn't apply here\n    if mode == AliasMode.JSON:\n        # things like class_ should just be class\n        if suffix[-1] == '_':\n            suffix = suffix[:-1]\n        return _camel_to_dash(suffix).rstrip(string.digits)\n    # else alias mode is field\n    return _camel_to_snake(suffix).rstrip(string.digits)\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.dash_to_underscore","title":"dash_to_underscore(name)","text":"

                                                                            Convert dash to underscore.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def dash_to_underscore(name: str) -> str:\n\"\"\"Convert dash to underscore.\"\"\"\n    return name.replace('-', '_')\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.spaces_and_caps_to_lower_single_spaces","title":"spaces_and_caps_to_lower_single_spaces(spaced_str)","text":"

                                                                            Convert caps and duplicate spaces to lower with single spaces.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def spaces_and_caps_to_lower_single_spaces(spaced_str: str) -> str:\n\"\"\"Convert caps and duplicate spaces to lower with single spaces.\"\"\"\n    single_space = ' '.join(spaced_str.strip().split())\n    return single_space.lower()\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.spaces_and_caps_to_snake","title":"spaces_and_caps_to_snake(spaced_str)","text":"

                                                                            Convert caps and spaces to snake.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def spaces_and_caps_to_snake(spaced_str: str) -> str:\n\"\"\"Convert caps and spaces to snake.\"\"\"\n    underscored = '_'.join(spaced_str.strip().split())\n    return underscored.lower()\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.string_from_root","title":"string_from_root(item_with_root)","text":"

                                                                            Convert root to string if present.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def string_from_root(item_with_root: Optional[Any]) -> str:\n\"\"\"Convert root to string if present.\"\"\"\n    return as_string(item_with_root.__root__) if item_with_root else ''\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.strip_lower_equals","title":"strip_lower_equals(str_a, str_b)","text":"

                                                                            Safe test of lower string equality allowing Nones.

                                                                            If either argument is None the result is False because the intent is to report if they are equal as actual strings.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def strip_lower_equals(str_a: Optional[str], str_b: Optional[str]) -> bool:\n\"\"\"\n    Safe test of lower string equality allowing Nones.\n\n    If either argument is None the result is False because the intent is to report if they are equal as actual strings.\n    \"\"\"\n    if str_a is None or str_b is None:\n        return False\n    return str_a.strip().lower() == str_b.strip().lower()\n
                                                                            "},{"location":"api_reference/trestle.common.str_utils/#trestle.common.str_utils.underscore_to_dash","title":"underscore_to_dash(name)","text":"

                                                                            Convert underscore to dash and drop final dash if present.

                                                                            Source code in trestle/common/str_utils.py
                                                                            def underscore_to_dash(name: str) -> str:\n\"\"\"Convert underscore to dash and drop final dash if present.\"\"\"\n    converted = name.replace('_', '-')\n    return converted if converted[-1] != '-' else converted[:-1]\n
                                                                            "},{"location":"api_reference/trestle.common.trash/","title":"trash","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash","title":"trestle.common.trash","text":"

                                                                            Trestle trash module.

                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.TRESTLE_TRASH_DIR","title":"TRESTLE_TRASH_DIR","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.TRESTLE_TRASH_DIR_EXT","title":"TRESTLE_TRASH_DIR_EXT","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.TRESTLE_TRASH_FILE_EXT","title":"TRESTLE_TRASH_FILE_EXT","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.get_trash_root","title":"get_trash_root(path)","text":"

                                                                            Find the trestle trash root path.

                                                                            Source code in trestle/common/trash.py
                                                                            def get_trash_root(path: pathlib.Path) -> Optional[pathlib.Path]:\n\"\"\"Find the trestle trash root path.\"\"\"\n    if path is None or len(path.parts) <= 0:\n        return None\n\n    current = path\n    while len(current.parts) > 1:  # it must not be the system root directory\n        trash_dir = current / TRESTLE_TRASH_DIR\n        if trash_dir.exists() and trash_dir.is_dir():\n            return trash_dir\n        current = current.parent\n\n    return None\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.has_parent_path","title":"has_parent_path(sub_path, parent_path)","text":"

                                                                            Check if sub_path has the specified parent_dir path.

                                                                            Source code in trestle/common/trash.py
                                                                            def has_parent_path(sub_path: pathlib.Path, parent_path: pathlib.Path) -> bool:\n\"\"\"Check if sub_path has the specified parent_dir path.\"\"\"\n    # sub_path should be longer than parent path\n    if len(sub_path.parts) < len(parent_path.parts):\n        return False\n\n    for i, part in enumerate(parent_path.parts):\n        if part != sub_path.parts[i]:\n            return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.recover","title":"recover(dest_content_path, delete_trash=False)","text":"

                                                                            Recover the specified file or directory from the trash directory.

                                                                            dest_content_path: destination content path that needs to be recovered from trash It recovers the latest path content from trash if exists

                                                                            Source code in trestle/common/trash.py
                                                                            def recover(dest_content_path: pathlib.Path, delete_trash: bool = False) -> None:\n\"\"\"Recover the specified file or directory from the trash directory.\n\n    dest_content_path: destination content path that needs to be recovered from trash\n    It recovers the latest path content from trash if exists\n    \"\"\"\n    if dest_content_path.suffix != '':\n        return recover_file(dest_content_path, delete_trash)\n    return recover_dir(dest_content_path, delete_trash)\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.recover_dir","title":"recover_dir(dest_dir_path, delete_trash=False)","text":"

                                                                            Move the specified dir from the trash directory.

                                                                            dest_dir_path: destination path of the directory inside a trestle workspace

                                                                            It recovers the latest directory and contents from trash if exists

                                                                            Source code in trestle/common/trash.py
                                                                            def recover_dir(dest_dir_path: pathlib.Path, delete_trash: bool = False) -> None:\n\"\"\"Move the specified dir from the trash directory.\n\n    dest_dir_path: destination path of the directory inside a trestle workspace\n\n    It recovers the latest directory and contents from trash if exists\n    \"\"\"\n    trash_dir_path = to_trash_dir_path(dest_dir_path)\n    if not (trash_dir_path.exists() and trash_dir_path.is_dir()):\n        raise AssertionError(f'Specified path \"{dest_dir_path}\" could not be found in trash')\n\n    # move all files/directories under sub_path\n    for item_path in pathlib.Path.iterdir(trash_dir_path):\n        if item_path.is_file():\n            recover_file(to_origin_file_path(item_path), delete_trash)\n        elif item_path.is_dir():\n            recover_dir(to_origin_dir_path(item_path), delete_trash)\n\n    if delete_trash:\n        trash_dir_path.rmdir()\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.recover_file","title":"recover_file(file_path, delete_trash=False)","text":"

                                                                            Recover the specified file from the trash directory.

                                                                            It recovers the latest file from trash if exists

                                                                            Source code in trestle/common/trash.py
                                                                            def recover_file(file_path: pathlib.Path, delete_trash: bool = False) -> None:\n\"\"\"Recover the specified file from the trash directory.\n\n    It recovers the latest file from trash if exists\n    \"\"\"\n    trash_file_path = to_trash_file_path(file_path)\n    if not trash_file_path.exists():\n        raise AssertionError(f'Specified path \"{file_path}\" could not be found in trash')\n\n    file_path.parent.mkdir(exist_ok=True, parents=True)\n    copyfile(trash_file_path, file_path)\n\n    if delete_trash:\n        trash_file_path.unlink()\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.store","title":"store(content_path, delete_content=False)","text":"

                                                                            Move the specified file or directory to the trash directory.

                                                                            It overwrites the previous file or directory if exists

                                                                            Source code in trestle/common/trash.py
                                                                            def store(content_path: pathlib.Path, delete_content: bool = False) -> None:\n\"\"\"Move the specified file or directory to the trash directory.\n\n    It overwrites the previous file or directory if exists\n    \"\"\"\n    if content_path.is_file():\n        return store_file(content_path, delete_content)\n    if content_path.is_dir():\n        return store_dir(content_path, delete_content)\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.store_dir","title":"store_dir(dir_path, delete_source=False)","text":"

                                                                            Move the specified dir to the trash directory.

                                                                            It overwrites the previous directory and contents if exists

                                                                            Source code in trestle/common/trash.py
                                                                            def store_dir(dir_path: pathlib.Path, delete_source: bool = False) -> None:\n\"\"\"Move the specified dir to the trash directory.\n\n    It overwrites the previous directory and contents if exists\n    \"\"\"\n    if not dir_path.is_dir():\n        raise AssertionError(f'Specified path \"{dir_path}\" is not a dir')\n\n    # move all files/directories under sub_path\n    for item_path in pathlib.Path.iterdir(dir_path):\n        if item_path.is_file():\n            store_file(item_path, delete_source)\n        elif item_path.is_dir():\n            store_dir(item_path, delete_source)\n\n    if delete_source:\n        dir_path.rmdir()\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.store_file","title":"store_file(file_path, delete_source=False)","text":"

                                                                            Move the specified file to the trash directory.

                                                                            It overwrites the previous file if exists

                                                                            Source code in trestle/common/trash.py
                                                                            def store_file(file_path: pathlib.Path, delete_source: bool = False) -> None:\n\"\"\"Move the specified file to the trash directory.\n\n    It overwrites the previous file if exists\n    \"\"\"\n    if not file_path.is_file():\n        raise AssertionError(f'Specified path \"{file_path}\" is not a file')\n\n    trash_file_path = to_trash_file_path(file_path)\n    trash_file_path.parent.mkdir(exist_ok=True, parents=True)\n    copyfile(file_path, trash_file_path)\n\n    if delete_source:\n        file_path.unlink()\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_origin_dir_path","title":"to_origin_dir_path(trash_dir_path)","text":"

                                                                            Convert trash content path to origin path.

                                                                            Source code in trestle/common/trash.py
                                                                            def to_origin_dir_path(trash_dir_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert trash content path to origin path.\"\"\"\n    if trash_dir_path.suffix != '' and trash_dir_path.suffix.endswith(TRESTLE_TRASH_FILE_EXT):\n        raise AssertionError(f'Given path \"{trash_dir_path}\" is a trash file, not a valid trash directory')\n\n    trestle_root = file_utils.extract_trestle_project_root(trash_dir_path)\n    if trestle_root is None:\n        raise AssertionError(f'Directory path \"{trash_dir_path}\" is not in a valid trestle project path')\n\n    trash_root = get_trash_root(trash_dir_path)\n    if trash_root is None:\n        raise AssertionError(f'Directory path \"{trash_dir_path}\" is not in a valid trestle trash path')\n\n    if not has_parent_path(trash_dir_path, trash_root):\n        raise AssertionError(f'Directory path \"{trash_dir_path}\" is not a valid trash dir path')\n\n    relative_path = trash_dir_path.relative_to(str(trash_root))\n\n    origin_path_parts: List[str] = []\n    for item in relative_path.parts:\n        parts = item.split(TRESTLE_TRASH_DIR_EXT)\n        origin_path_parts.append(parts[0])\n\n    origin_relative_path = pathlib.Path('/'.join(origin_path_parts))\n    origin_path = trestle_root / origin_relative_path\n    return origin_path\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_origin_file_path","title":"to_origin_file_path(trash_file_path)","text":"

                                                                            Convert trash file path to origin file path.

                                                                            Source code in trestle/common/trash.py
                                                                            def to_origin_file_path(trash_file_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert trash file path to origin file path.\"\"\"\n    if trash_file_path.suffix != TRESTLE_TRASH_FILE_EXT:\n        raise AssertionError(f'File path \"{trash_file_path}\" is not a valid trash file path')\n\n    origin_dir = to_origin_dir_path(trash_file_path.parent)\n    file_parts = trash_file_path.name.split(TRESTLE_TRASH_FILE_EXT)\n    origin_file_path = origin_dir / file_parts[0]\n\n    return origin_file_path\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_origin_path","title":"to_origin_path(trash_content_path)","text":"

                                                                            Convert the trash path to origin path.

                                                                            Source code in trestle/common/trash.py
                                                                            def to_origin_path(trash_content_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert the trash path to origin path.\"\"\"\n    if trash_content_path.suffix == TRESTLE_TRASH_FILE_EXT:\n        return to_origin_file_path(trash_content_path)\n    return to_origin_dir_path(trash_content_path)\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_trash_dir_path","title":"to_trash_dir_path(dir_path)","text":"

                                                                            Construct the path to the trashed file.

                                                                            Source code in trestle/common/trash.py
                                                                            def to_trash_dir_path(dir_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Construct the path to the trashed file.\"\"\"\n    absolute_path = dir_path.resolve()\n    root_path = file_utils.extract_trestle_project_root(absolute_path)\n    if root_path is None:\n        raise AssertionError(f'Directory path \"{absolute_path}\" is not in a valid trestle project')\n\n    trestle_trash_path = root_path / TRESTLE_TRASH_DIR\n\n    relative_path = absolute_path.relative_to(str(root_path))\n    if len(relative_path.parts) == 0:\n        trash_dir = trestle_trash_path\n    else:\n        trash_dir = trestle_trash_path / f'{relative_path}{TRESTLE_TRASH_DIR_EXT}'\n\n    return trash_dir\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_trash_file_path","title":"to_trash_file_path(file_path)","text":"

                                                                            Construct the path to the trashed file.

                                                                            Source code in trestle/common/trash.py
                                                                            def to_trash_file_path(file_path: pathlib.Path) -> pathlib.Path:\n\"\"\"Construct the path to the trashed file.\"\"\"\n    trash_file_dir = to_trash_dir_path(file_path.parent)\n    trash_file_path = trash_file_dir / f'{file_path.name}{TRESTLE_TRASH_FILE_EXT}'\n\n    return trash_file_path\n
                                                                            "},{"location":"api_reference/trestle.common.trash/#trestle.common.trash.to_trash_path","title":"to_trash_path(path)","text":"

                                                                            Convert the dir or file path to apporpriate trash file or dir path.

                                                                            Source code in trestle/common/trash.py
                                                                            def to_trash_path(path: pathlib.Path) -> pathlib.Path:\n\"\"\"Convert the dir or file path to apporpriate trash file or dir path.\"\"\"\n    if path.suffix != '':\n        return to_trash_file_path(path)\n    return to_trash_dir_path(path)\n
                                                                            "},{"location":"api_reference/trestle.common.type_utils/","title":"type_utils","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils","title":"trestle.common.type_utils","text":"

                                                                            Utilities for dealing with models.

                                                                            "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.logger","title":"logger","text":""},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.get_inner_type","title":"get_inner_type(collection_field_type)","text":"

                                                                            Get the inner model in a generic collection model such as a List or a Dict.

                                                                            For a dict the return type is of the value and not the key.

                                                                            Parameters:

                                                                            Name Type Description Default collection_field_type Union[Type[List[Any]], Type[Dict[str, Any]]]

                                                                            Provided type annotation from a pydantic object

                                                                            required

                                                                            Returns:

                                                                            Type Description Type[Any]

                                                                            The desired type.

                                                                            Source code in trestle/common/type_utils.py
                                                                            def get_inner_type(collection_field_type: Union[Type[List[Any]], Type[Dict[str, Any]]]) -> Type[Any]:\n\"\"\"Get the inner model in a generic collection model such as a List or a Dict.\n\n    For a dict the return type is of the value and not the key.\n\n    Args:\n        collection_field_type: Provided type annotation from a pydantic object\n\n    Returns:\n        The desired type.\n    \"\"\"\n    try:\n        # Pydantic special cases must be dealt with here:\n        _, _, singular_type = _get_model_field_info(collection_field_type)\n        if singular_type is not None:\n            return singular_type\n        return typing_extensions.get_args(collection_field_type)[-1]\n    except Exception as e:\n        logger.debug(e)\n        raise err.TrestleError('Model type is not a Dict or List') from e\n
                                                                            "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.get_origin","title":"get_origin(field_type)","text":"

                                                                            Generalized and robust get_origin function.

                                                                            This function is derived from work by pydantic, however, avoids complications from various python versions.

                                                                            Source code in trestle/common/type_utils.py
                                                                            def get_origin(field_type: Type[Any]) -> Optional[Type[Any]]:\n\"\"\"Generalized and robust get_origin function.\n\n    This function is derived from work by pydantic, however, avoids complications\n    from various python versions.\n    \"\"\"\n    # This executes a fallback that allows a list to be generated from a constrained list.\n    return typing_extensions.get_origin(field_type) or getattr(field_type, '__origin__', None)\n
                                                                            "},{"location":"api_reference/trestle.common.type_utils/#trestle.common.type_utils.is_collection_field_type","title":"is_collection_field_type(field_type)","text":"

                                                                            Check whether a type hint is a collection type as used by OSCAL.

                                                                            Specifically this is whether the type is a list or not.

                                                                            Parameters:

                                                                            Name Type Description Default field_type Type[Any]

                                                                            A type or a type alias of a field typically as served via pydantic introspection

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            True if it is a collection type list.

                                                                            Source code in trestle/common/type_utils.py
                                                                            def is_collection_field_type(field_type: Type[Any]) -> bool:\n\"\"\"Check whether a type hint is a collection type as used by OSCAL.\n\n    Specifically this is whether the type is a list or not.\n\n    Args:\n        field_type: A type or a type alias of a field typically as served via pydantic introspection\n\n    Returns:\n        True if it is a collection type list.\n    \"\"\"\n    # first check if it is a pydantic __root__ object\n    _, root_type, _ = _get_model_field_info(field_type)\n    if root_type == 'List':\n        return True\n    # Retrieves type from a type annotation\n    origin_type = get_origin(field_type)\n    return origin_type == list\n
                                                                            "},{"location":"api_reference/trestle.core.all_validator/","title":"all_validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator","title":"trestle.core.all_validator","text":"

                                                                            Validate based on all registered validators.

                                                                            "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator","title":" AllValidator (Validator) ","text":"

                                                                            Validator to confirm the model passes all registered validation tests.

                                                                            Source code in trestle/core/all_validator.py
                                                                            class AllValidator(Validator):\n\"\"\"Validator to confirm the model passes all registered validation tests.\"\"\"\n\n    last_failure_msg: str\n\n    def error_msg(self) -> str:\n\"\"\"Return information on which validation failed.\"\"\"\n        return self.last_failure_msg\n\n    def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n        Validate an oscal model against all available validators in the trestle library.\n\n        args:\n            model: An Oscal model that can be passed to the validator.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if the model passed all registered validators.\n        \"\"\"\n        self.last_failure_msg = self.__doc__\n        for val in vfact.validator_factory.get_all():\n            if val != self and not val.model_is_valid(model, quiet, trestle_root):\n                self.last_failure_msg = val.error_msg()\n                return False\n        return True\n
                                                                            "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator.error_msg","title":"error_msg(self)","text":"

                                                                            Return information on which validation failed.

                                                                            Source code in trestle/core/all_validator.py
                                                                            def error_msg(self) -> str:\n\"\"\"Return information on which validation failed.\"\"\"\n    return self.last_failure_msg\n
                                                                            "},{"location":"api_reference/trestle.core.all_validator/#trestle.core.all_validator.AllValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                                                            Validate an oscal model against all available validators in the trestle library.

                                                                            Parameters:

                                                                            Name Type Description Default model OscalBaseModel

                                                                            An Oscal model that can be passed to the validator.

                                                                            required quiet bool

                                                                            Don't report msgs unless invalid.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            True (valid) if the model passed all registered validators.

                                                                            Source code in trestle/core/all_validator.py
                                                                            def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n    Validate an oscal model against all available validators in the trestle library.\n\n    args:\n        model: An Oscal model that can be passed to the validator.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if the model passed all registered validators.\n    \"\"\"\n    self.last_failure_msg = self.__doc__\n    for val in vfact.validator_factory.get_all():\n        if val != self and not val.model_is_valid(model, quiet, trestle_root):\n            self.last_failure_msg = val.error_msg()\n            return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/","title":"base_model","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model","title":"trestle.core.base_model","text":"

                                                                            Pydantic base model for use within a trestle workspace and associated configuration.

                                                                            The heart of the current OSCAL model within trestle is based on pydantic (https://pydantic-docs.helpmanual.io/) which itself is a veneer on-top of python data classes.

                                                                            Functionality here defines a base-model which all trestle oscal data models inherit from. This allows additional functionality to be easily inserted.

                                                                            I can write a comment in here and you can even edit on the same line.

                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel","title":" OscalBaseModel (TrestleBaseModel) pydantic-model","text":"

                                                                            Trestle defined pydantic base model for use with OSCAL pydantic dataclasses.

                                                                            This BaseModel provides two types of functionality: 1. Overrides default configuation of the pydantic library with behaviours required for trestle 2. Provides utility functions for trestle which are specific to OSCAL and the naming schema associated with it.

                                                                            Source code in trestle/core/base_model.py
                                                                            class OscalBaseModel(TrestleBaseModel):\n\"\"\"\n    Trestle defined pydantic base model for use with OSCAL pydantic dataclasses.\n\n    This BaseModel provides two types of functionality:\n    1. Overrides default configuation of the pydantic library with behaviours required for trestle\n    2. Provides utility functions for trestle which are specific to OSCAL and the naming schema associated with it.\n    \"\"\"\n\n    class Config:\n\"\"\"Overriding configuration class for pydantic base model, for use with OSCAL data classes.\"\"\"\n\n        json_loads = orjson.loads\n        # TODO: json_dumps with orjson.dumps see #840\n\n        json_encoders = {datetime.datetime: lambda x: robust_datetime_serialization(x)}\n        allow_population_by_field_name = True\n\n        # Enforce strict schema\n        extra = Extra.forbid\n\n        # Validate on assignment of variables to ensure no escapes\n        validate_assignment = True\n\n    @classmethod\n    def create_stripped_model_type(\n        cls,\n        stripped_fields: Optional[List[str]] = None,\n        stripped_fields_aliases: Optional[List[str]] = None\n    ) -> Type['OscalBaseModel']:\n\"\"\"Create a pydantic model, which is derived from the current model, but missing certain fields.\n\n        OSCAL mandates a 'strict' schema (e.g. unless otherwise stated no additional fields), and certain fields\n        are mandatory. Given this the corresponding dataclasses are also strict. Workflows with trestle require missing\n        mandatory fields. This allows creation of derivative models missing certain fields.\n\n        Args:\n            stripped_fields: The fields to be removed from the current data class.\n            stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n        Returns:\n            Pydantic data class thta can be used to instanciate a model.\n\n        Raises:\n            TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n            TrestleError: If incorrect aliases or field names are provided.\n        \"\"\"\n        if stripped_fields is not None and stripped_fields_aliases is not None:\n            raise err.TrestleError('Either \"stripped_fields\" or \"stripped_fields_aliases\" need to be passed, not both.')\n        if stripped_fields is None and stripped_fields_aliases is None:\n            raise err.TrestleError('Exactly one of \"stripped_fields\" or \"stripped_fields_aliases\" must be provided')\n\n        # create alias to field_name mapping\n        excluded_fields = []\n        if stripped_fields is not None:\n            excluded_fields = stripped_fields\n        elif stripped_fields_aliases is not None:\n            alias_to_field = cls.alias_to_field_map()\n            try:\n                excluded_fields = [alias_to_field[key].name for key in stripped_fields_aliases]\n            except KeyError as e:\n                raise err.TrestleError(f'Field {str(e)} does not exist in the model')\n\n        current_fields = cls.__fields__\n        new_fields_for_model = {}\n        # Build field list\n        for current_mfield in current_fields.values():\n            if current_mfield.name in excluded_fields:\n                continue\n            # Validate name in the field\n            # Cehcke behaviour with an alias\n            if current_mfield.required:\n                new_fields_for_model[\n                    current_mfield.name\n                ] = (current_mfield.outer_type_, Field(..., title=current_mfield.name, alias=current_mfield.alias))\n            else:\n                new_fields_for_model[current_mfield.name] = (\n                    Optional[current_mfield.outer_type_],\n                    Field(None, title=current_mfield.name, alias=current_mfield.alias)\n                )\n        new_model = create_model(cls.__name__, __base__=OscalBaseModel, **new_fields_for_model)  # type: ignore\n        # TODO: This typing cast should NOT be necessary. Potentially fixable with a fix to pydantic. Issue #175\n        new_model = cast(Type[OscalBaseModel], new_model)\n\n        return new_model\n\n    def get_field_by_alias(self, field_alias: str) -> Any:\n\"\"\"Convert field alias to a field.\"\"\"\n        attr_field = self.alias_to_field_map().get(field_alias, None)\n        return attr_field\n\n    def get_field_value_by_alias(self, attr_alias: str) -> Optional[Any]:\n\"\"\"Get attribute value by field alias.\"\"\"\n        # TODO: can this be restricted beyond Any easily.\n        attr_field = self.get_field_by_alias(attr_alias)\n        if isinstance(attr_field, ModelField):\n            return getattr(self, attr_field.name, None)\n\n        return None\n\n    def stripped_instance(\n        self,\n        stripped_fields: Optional[List[str]] = None,\n        stripped_fields_aliases: Optional[List[str]] = None\n    ) -> 'OscalBaseModel':\n\"\"\"Return a new model instance with the specified fields being stripped.\n\n        Args:\n            stripped_fields: The fields to be removed from the current data class.\n            stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n        Returns:\n            The current datamodel with the fields provided removed in a derivate (run time created) data model.\n\n        Raises:\n            err.TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n            err.TrestleError: If incorrect aliases or field names are provided.\n        \"\"\"\n        # stripped class type\n        stripped_class: Type[OscalBaseModel] = self.create_stripped_model_type(\n            stripped_fields=stripped_fields, stripped_fields_aliases=stripped_fields_aliases\n        )\n\n        # remaining values\n        remaining_values = {}\n        for field in self.__fields__.values():\n            if field.name in stripped_class.__fields__:\n                remaining_values[field.name] = self.__dict__[field.name]\n\n        # create stripped model instance\n        # TODO: Not sure if we can avoid type escapes here\n        stripped_instance = stripped_class(**remaining_values)\n\n        return stripped_instance\n\n    def oscal_dict(self) -> Dict[str, Any]:\n\"\"\"Return a dictionary including the root wrapping object key.\"\"\"\n        class_name = self.__class__.__name__\n        result = {}\n        raw_dict = self.dict(by_alias=True, exclude_none=True)\n        # Additional check to avoid root serialization\n        if '__root__' in raw_dict.keys():\n            result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict['__root__']\n        else:\n            result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict\n        return result\n\n    def oscal_serialize_json_bytes(self, pretty: bool = False, wrapped: bool = True) -> bytes:\n\"\"\"\n        Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n        Args:\n            pretty: Whether or not to pretty-print json output or have in compressed form.\n        Returns:\n            Oscal model serialized to a json object including packaging inside of a single top level key.\n        \"\"\"\n        if wrapped:\n            odict = self.oscal_dict()\n        else:\n            odict = self.dict(by_alias=True, exclude_none=True)\n        if pretty:\n            return orjson.dumps(odict, default=self.__json_encoder__, option=orjson.OPT_INDENT_2)  # type: ignore\n        return orjson.dumps(odict, default=self.__json_encoder__)  # type: ignore\n\n    def oscal_serialize_json(self, pretty: bool = False, wrapped: bool = True) -> str:\n\"\"\"\n        Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n        Args:\n            pretty: Whether or not to pretty-print json output or have in compressed form.\n        Returns:\n            Oscal model serialized to a json object including packaging inside of a single top level key.\n        \"\"\"\n        # This function is provided for backwards compatibility\n        return self.oscal_serialize_json_bytes(pretty, wrapped).decode(const.FILE_ENCODING)\n\n    def oscal_write(self, path: pathlib.Path) -> None:\n\"\"\"\n        Write out a pydantic data model in an oscal friendly way.\n\n        OSCAL schema mandates that top level elements are wrapped in a singular\n        json/yaml field. This function handles both json and yaml output as well\n        as formatting of the json.\n\n        Args:\n            path: The output file location for the oscal object.\n\n        Raises:\n            err.TrestleError: If a unknown file extension is provided.\n        \"\"\"\n        content_type = FileContentType.to_content_type(path.suffix)\n        # The output will have \\r\\n newlines on windows and \\n newlines elsewhere\n\n        if content_type == FileContentType.YAML:\n            write_file = pathlib.Path(path).open('w', encoding=const.FILE_ENCODING)\n            yaml = YAML(typ='safe')\n            yaml.dump(yaml.load(self.oscal_serialize_json()), write_file)\n            write_file.flush()\n            write_file.close()\n        elif content_type == FileContentType.JSON:\n            write_file = pathlib.Path(path).open('wb')  # type: ignore\n            write_file.write(self.oscal_serialize_json_bytes(pretty=True))  # type: ignore\n            # Flush / close required (by experience) due to flushing issues in tests.\n            write_file.flush()\n            write_file.close()\n\n    @classmethod\n    def oscal_read(cls, path: pathlib.Path) -> Optional['OscalBaseModel']:\n\"\"\"\n        Read OSCAL objects.\n\n        Handles the fact OSCAL wraps top level elements and also deals with both yaml and json.\n\n        Args:\n            path: The path of the oscal object to read.\n        Returns:\n            The oscal object read into trestle oscal models.\n        \"\"\"\n        # Create the wrapper model.\n        alias = classname_to_alias(cls.__name__, AliasMode.JSON)\n\n        content_type = FileContentType.to_content_type(path.suffix)\n        logger.debug(f'oscal_read content type {content_type} and alias {alias} from {path}')\n\n        if not path.exists():\n            logger.warning(f'path does not exist in oscal_read: {path}')\n            return None\n\n        obj: Dict[str, Any] = {}\n        try:\n            if content_type == FileContentType.YAML:\n                yaml = YAML(typ='safe')\n                fh = path.open('r', encoding=const.FILE_ENCODING)\n                obj = yaml.load(fh)\n                fh.close()\n            elif content_type == FileContentType.JSON:\n                obj = load_file(\n                    path,\n                    json_loads=cls.__config__.json_loads,\n                )\n        except Exception as e:\n            raise err.TrestleError(f'Error loading file {path} {str(e)}')\n        try:\n            if not len(obj) == 1:\n                raise err.TrestleError(\n                    f'Invalid OSCAL file structure, oscal file '\n                    f'does not have a single top level key wrapping it. It has {len(obj)} keys.'\n                )\n            parsed = cls.parse_obj(obj[alias])\n        except KeyError:\n            raise err.TrestleError(f'Provided oscal file does not have top level key key: {alias}')\n        except Exception as e:\n            raise err.TrestleError(f'Error parsing file {path} {str(e)}')\n\n        return parsed\n\n    def copy_to(self, new_oscal_type: Type['OscalBaseModel']) -> 'OscalBaseModel':\n\"\"\"\n        Opportunistic copy operation between similar types of data classes.\n\n        Due to the way in which oscal is constructed we get a set of similar / the same definition across various\n        oscal models. Due to the lack of guarantees that they are the same we cannot easily 'collapse' the mode.\n\n        Args:\n            new_oscal_type: The desired type of oscal model\n\n        Returns:\n            Opportunistic copy of the data into the new model type.\n        \"\"\"\n        logger.debug('Copy to started')\n        if self.__class__.__name__ == new_oscal_type.__name__:\n            logger.debug('Json based copy')\n            # Note: Json based oppportunistic copy\n            # Dev notes: Do not change this from json. Due to enums (in particular) json is the closest we can get.\n            return new_oscal_type.parse_raw(self.oscal_serialize_json(pretty=False, wrapped=False))\n\n        if ('__root__' in self.__fields__ and len(self.__fields__) == 1 and '__root__' in new_oscal_type.__fields__\n                and len(new_oscal_type.__fields__) == 1):\n            logger.debug('Root element based copy too')\n            return new_oscal_type.parse_obj(self.__root__)  # type: ignore\n\n        # bad place here.\n        raise err.TrestleError('Provided inconsistent classes to copy to methodology.')\n\n    def copy_from(self, existing_oscal_object: 'OscalBaseModel') -> None:\n\"\"\"\n        Copy operation that implicitly does type conversion.\n\n        Typically would\n        be used to set an attribute, however, does not need to be.\n\n        Deals with two scenarios:\n        1) Casting across oscal models of equivalent type. The purpose if this\n        is to cross class spaces.\n\n        2) The same as above where the item is an array style object which does\n        not correctly serialize to a dict.\n\n        3) if the from and 'to' objects are root schema elements the copy operation\n        will copy the root element to the value.\n\n        Args:\n            existing_oscal_object: The oscal object where fields are copied from.\n\n        \"\"\"\n        recast_object = existing_oscal_object.copy_to(self.__class__)\n        for raw_field in self.__dict__:\n            self.__dict__[raw_field] = recast_object.__dict__[raw_field]\n\n    @classmethod\n    def alias_to_field_map(cls) -> Dict[str, ModelField]:\n\"\"\"Create a map from field alias to field.\n\n        Returns:\n            A dict which has key's of aliases and Fields as values.\n        \"\"\"\n        alias_to_field: Dict[str, ModelField] = {}\n        for field in cls.__fields__.values():\n            alias_to_field[field.alias] = field\n\n        return alias_to_field\n\n    @classmethod\n    def is_collection_container(cls) -> bool:\n\"\"\"\n        Determine whether a pydantic model has being created to wrap a collection primitive (e.g a list or dict).\n\n        In performing model decomposition it is possible using trestle framework to automatically generate a model\n        which looks like\n\n        class Foo(OscalBaseModel):\n            __root__: List[Bar]\n\n        Returns:\n            Boolean on if it meets the above criteria\n\n        When these cases exist we need special handling of the type information.\n        \"\"\"\n        # Additional sanity check on field length\n        if len(cls.__fields__) == 1 and '__root__' in cls.__fields__:\n            # This is now a __root__ key only model\n            if is_collection_field_type(cls.__fields__['__root__'].outer_type_):\n                return True\n        return False\n\n    @classmethod\n    def get_collection_type(cls) -> Optional[type]:\n\"\"\"\n        If the type wraps an collection, return the collection type.\n\n        Returns:\n            The collection type.\n\n        Raises:\n            err.TrestleError: if not a wrapper of the collection type.\n        \"\"\"\n        if not cls.is_collection_container():\n            raise err.TrestleError('OscalBaseModel is not wrapping a collection type')\n        return get_origin(cls.__fields__['__root__'].outer_type_)\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.Config","title":" Config ","text":"

                                                                            Overriding configuration class for pydantic base model, for use with OSCAL data classes.

                                                                            Source code in trestle/core/base_model.py
                                                                            class Config:\n\"\"\"Overriding configuration class for pydantic base model, for use with OSCAL data classes.\"\"\"\n\n    json_loads = orjson.loads\n    # TODO: json_dumps with orjson.dumps see #840\n\n    json_encoders = {datetime.datetime: lambda x: robust_datetime_serialization(x)}\n    allow_population_by_field_name = True\n\n    # Enforce strict schema\n    extra = Extra.forbid\n\n    # Validate on assignment of variables to ensure no escapes\n    validate_assignment = True\n
                                                                            allow_population_by_field_name \u00a4 extra \u00a4 json_encoders \u00a4 json_loads \u00a4 validate_assignment \u00a4"},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.alias_to_field_map","title":"alias_to_field_map() classmethod","text":"

                                                                            Create a map from field alias to field.

                                                                            Returns:

                                                                            Type Description Dict[str, pydantic.v1.fields.ModelField]

                                                                            A dict which has key's of aliases and Fields as values.

                                                                            Source code in trestle/core/base_model.py
                                                                            @classmethod\ndef alias_to_field_map(cls) -> Dict[str, ModelField]:\n\"\"\"Create a map from field alias to field.\n\n    Returns:\n        A dict which has key's of aliases and Fields as values.\n    \"\"\"\n    alias_to_field: Dict[str, ModelField] = {}\n    for field in cls.__fields__.values():\n        alias_to_field[field.alias] = field\n\n    return alias_to_field\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.copy_from","title":"copy_from(self, existing_oscal_object)","text":"

                                                                            Copy operation that implicitly does type conversion.

                                                                            Typically would be used to set an attribute, however, does not need to be.

                                                                            Deals with two scenarios: 1) Casting across oscal models of equivalent type. The purpose if this is to cross class spaces.

                                                                            2) The same as above where the item is an array style object which does not correctly serialize to a dict.

                                                                            3) if the from and 'to' objects are root schema elements the copy operation will copy the root element to the value.

                                                                            Parameters:

                                                                            Name Type Description Default existing_oscal_object OscalBaseModel

                                                                            The oscal object where fields are copied from.

                                                                            required Source code in trestle/core/base_model.py
                                                                            def copy_from(self, existing_oscal_object: 'OscalBaseModel') -> None:\n\"\"\"\n    Copy operation that implicitly does type conversion.\n\n    Typically would\n    be used to set an attribute, however, does not need to be.\n\n    Deals with two scenarios:\n    1) Casting across oscal models of equivalent type. The purpose if this\n    is to cross class spaces.\n\n    2) The same as above where the item is an array style object which does\n    not correctly serialize to a dict.\n\n    3) if the from and 'to' objects are root schema elements the copy operation\n    will copy the root element to the value.\n\n    Args:\n        existing_oscal_object: The oscal object where fields are copied from.\n\n    \"\"\"\n    recast_object = existing_oscal_object.copy_to(self.__class__)\n    for raw_field in self.__dict__:\n        self.__dict__[raw_field] = recast_object.__dict__[raw_field]\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.copy_to","title":"copy_to(self, new_oscal_type)","text":"

                                                                            Opportunistic copy operation between similar types of data classes.

                                                                            Due to the way in which oscal is constructed we get a set of similar / the same definition across various oscal models. Due to the lack of guarantees that they are the same we cannot easily 'collapse' the mode.

                                                                            Parameters:

                                                                            Name Type Description Default new_oscal_type Type[OscalBaseModel]

                                                                            The desired type of oscal model

                                                                            required

                                                                            Returns:

                                                                            Type Description OscalBaseModel

                                                                            Opportunistic copy of the data into the new model type.

                                                                            Source code in trestle/core/base_model.py
                                                                            def copy_to(self, new_oscal_type: Type['OscalBaseModel']) -> 'OscalBaseModel':\n\"\"\"\n    Opportunistic copy operation between similar types of data classes.\n\n    Due to the way in which oscal is constructed we get a set of similar / the same definition across various\n    oscal models. Due to the lack of guarantees that they are the same we cannot easily 'collapse' the mode.\n\n    Args:\n        new_oscal_type: The desired type of oscal model\n\n    Returns:\n        Opportunistic copy of the data into the new model type.\n    \"\"\"\n    logger.debug('Copy to started')\n    if self.__class__.__name__ == new_oscal_type.__name__:\n        logger.debug('Json based copy')\n        # Note: Json based oppportunistic copy\n        # Dev notes: Do not change this from json. Due to enums (in particular) json is the closest we can get.\n        return new_oscal_type.parse_raw(self.oscal_serialize_json(pretty=False, wrapped=False))\n\n    if ('__root__' in self.__fields__ and len(self.__fields__) == 1 and '__root__' in new_oscal_type.__fields__\n            and len(new_oscal_type.__fields__) == 1):\n        logger.debug('Root element based copy too')\n        return new_oscal_type.parse_obj(self.__root__)  # type: ignore\n\n    # bad place here.\n    raise err.TrestleError('Provided inconsistent classes to copy to methodology.')\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.create_stripped_model_type","title":"create_stripped_model_type(stripped_fields=None, stripped_fields_aliases=None) classmethod","text":"

                                                                            Create a pydantic model, which is derived from the current model, but missing certain fields.

                                                                            OSCAL mandates a 'strict' schema (e.g. unless otherwise stated no additional fields), and certain fields are mandatory. Given this the corresponding dataclasses are also strict. Workflows with trestle require missing mandatory fields. This allows creation of derivative models missing certain fields.

                                                                            Parameters:

                                                                            Name Type Description Default stripped_fields Optional[List[str]]

                                                                            The fields to be removed from the current data class.

                                                                            None stripped_fields_aliases Optional[List[str]]

                                                                            The fields to be removed from the current data class provided by alias.

                                                                            None

                                                                            Returns:

                                                                            Type Description Type[OscalBaseModel]

                                                                            Pydantic data class thta can be used to instanciate a model.

                                                                            Exceptions:

                                                                            Type Description TrestleError

                                                                            If user provided both stripped_fields and stripped_field_aliases or neither.

                                                                            TrestleError

                                                                            If incorrect aliases or field names are provided.

                                                                            Source code in trestle/core/base_model.py
                                                                            @classmethod\ndef create_stripped_model_type(\n    cls,\n    stripped_fields: Optional[List[str]] = None,\n    stripped_fields_aliases: Optional[List[str]] = None\n) -> Type['OscalBaseModel']:\n\"\"\"Create a pydantic model, which is derived from the current model, but missing certain fields.\n\n    OSCAL mandates a 'strict' schema (e.g. unless otherwise stated no additional fields), and certain fields\n    are mandatory. Given this the corresponding dataclasses are also strict. Workflows with trestle require missing\n    mandatory fields. This allows creation of derivative models missing certain fields.\n\n    Args:\n        stripped_fields: The fields to be removed from the current data class.\n        stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n    Returns:\n        Pydantic data class thta can be used to instanciate a model.\n\n    Raises:\n        TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n        TrestleError: If incorrect aliases or field names are provided.\n    \"\"\"\n    if stripped_fields is not None and stripped_fields_aliases is not None:\n        raise err.TrestleError('Either \"stripped_fields\" or \"stripped_fields_aliases\" need to be passed, not both.')\n    if stripped_fields is None and stripped_fields_aliases is None:\n        raise err.TrestleError('Exactly one of \"stripped_fields\" or \"stripped_fields_aliases\" must be provided')\n\n    # create alias to field_name mapping\n    excluded_fields = []\n    if stripped_fields is not None:\n        excluded_fields = stripped_fields\n    elif stripped_fields_aliases is not None:\n        alias_to_field = cls.alias_to_field_map()\n        try:\n            excluded_fields = [alias_to_field[key].name for key in stripped_fields_aliases]\n        except KeyError as e:\n            raise err.TrestleError(f'Field {str(e)} does not exist in the model')\n\n    current_fields = cls.__fields__\n    new_fields_for_model = {}\n    # Build field list\n    for current_mfield in current_fields.values():\n        if current_mfield.name in excluded_fields:\n            continue\n        # Validate name in the field\n        # Cehcke behaviour with an alias\n        if current_mfield.required:\n            new_fields_for_model[\n                current_mfield.name\n            ] = (current_mfield.outer_type_, Field(..., title=current_mfield.name, alias=current_mfield.alias))\n        else:\n            new_fields_for_model[current_mfield.name] = (\n                Optional[current_mfield.outer_type_],\n                Field(None, title=current_mfield.name, alias=current_mfield.alias)\n            )\n    new_model = create_model(cls.__name__, __base__=OscalBaseModel, **new_fields_for_model)  # type: ignore\n    # TODO: This typing cast should NOT be necessary. Potentially fixable with a fix to pydantic. Issue #175\n    new_model = cast(Type[OscalBaseModel], new_model)\n\n    return new_model\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.get_collection_type","title":"get_collection_type() classmethod","text":"

                                                                            If the type wraps an collection, return the collection type.

                                                                            Returns:

                                                                            Type Description Optional[type]

                                                                            The collection type.

                                                                            Exceptions:

                                                                            Type Description err.TrestleError

                                                                            if not a wrapper of the collection type.

                                                                            Source code in trestle/core/base_model.py
                                                                            @classmethod\ndef get_collection_type(cls) -> Optional[type]:\n\"\"\"\n    If the type wraps an collection, return the collection type.\n\n    Returns:\n        The collection type.\n\n    Raises:\n        err.TrestleError: if not a wrapper of the collection type.\n    \"\"\"\n    if not cls.is_collection_container():\n        raise err.TrestleError('OscalBaseModel is not wrapping a collection type')\n    return get_origin(cls.__fields__['__root__'].outer_type_)\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.get_field_by_alias","title":"get_field_by_alias(self, field_alias)","text":"

                                                                            Convert field alias to a field.

                                                                            Source code in trestle/core/base_model.py
                                                                            def get_field_by_alias(self, field_alias: str) -> Any:\n\"\"\"Convert field alias to a field.\"\"\"\n    attr_field = self.alias_to_field_map().get(field_alias, None)\n    return attr_field\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.get_field_value_by_alias","title":"get_field_value_by_alias(self, attr_alias)","text":"

                                                                            Get attribute value by field alias.

                                                                            Source code in trestle/core/base_model.py
                                                                            def get_field_value_by_alias(self, attr_alias: str) -> Optional[Any]:\n\"\"\"Get attribute value by field alias.\"\"\"\n    # TODO: can this be restricted beyond Any easily.\n    attr_field = self.get_field_by_alias(attr_alias)\n    if isinstance(attr_field, ModelField):\n        return getattr(self, attr_field.name, None)\n\n    return None\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.is_collection_container","title":"is_collection_container() classmethod","text":"

                                                                            Determine whether a pydantic model has being created to wrap a collection primitive (e.g a list or dict).

                                                                            In performing model decomposition it is possible using trestle framework to automatically generate a model which looks like

                                                                            class Foo(OscalBaseModel): root: List[Bar]

                                                                            Returns:

                                                                            Type Description bool

                                                                            Boolean on if it meets the above criteria

                                                                            When these cases exist we need special handling of the type information.

                                                                            Source code in trestle/core/base_model.py
                                                                            @classmethod\ndef is_collection_container(cls) -> bool:\n\"\"\"\n    Determine whether a pydantic model has being created to wrap a collection primitive (e.g a list or dict).\n\n    In performing model decomposition it is possible using trestle framework to automatically generate a model\n    which looks like\n\n    class Foo(OscalBaseModel):\n        __root__: List[Bar]\n\n    Returns:\n        Boolean on if it meets the above criteria\n\n    When these cases exist we need special handling of the type information.\n    \"\"\"\n    # Additional sanity check on field length\n    if len(cls.__fields__) == 1 and '__root__' in cls.__fields__:\n        # This is now a __root__ key only model\n        if is_collection_field_type(cls.__fields__['__root__'].outer_type_):\n            return True\n    return False\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_dict","title":"oscal_dict(self)","text":"

                                                                            Return a dictionary including the root wrapping object key.

                                                                            Source code in trestle/core/base_model.py
                                                                            def oscal_dict(self) -> Dict[str, Any]:\n\"\"\"Return a dictionary including the root wrapping object key.\"\"\"\n    class_name = self.__class__.__name__\n    result = {}\n    raw_dict = self.dict(by_alias=True, exclude_none=True)\n    # Additional check to avoid root serialization\n    if '__root__' in raw_dict.keys():\n        result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict['__root__']\n    else:\n        result[classname_to_alias(class_name, AliasMode.JSON)] = raw_dict\n    return result\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_read","title":"oscal_read(path) classmethod","text":"

                                                                            Read OSCAL objects.

                                                                            Handles the fact OSCAL wraps top level elements and also deals with both yaml and json.

                                                                            Parameters:

                                                                            Name Type Description Default path Path

                                                                            The path of the oscal object to read.

                                                                            required

                                                                            Returns:

                                                                            Type Description Optional[OscalBaseModel]

                                                                            The oscal object read into trestle oscal models.

                                                                            Source code in trestle/core/base_model.py
                                                                            @classmethod\ndef oscal_read(cls, path: pathlib.Path) -> Optional['OscalBaseModel']:\n\"\"\"\n    Read OSCAL objects.\n\n    Handles the fact OSCAL wraps top level elements and also deals with both yaml and json.\n\n    Args:\n        path: The path of the oscal object to read.\n    Returns:\n        The oscal object read into trestle oscal models.\n    \"\"\"\n    # Create the wrapper model.\n    alias = classname_to_alias(cls.__name__, AliasMode.JSON)\n\n    content_type = FileContentType.to_content_type(path.suffix)\n    logger.debug(f'oscal_read content type {content_type} and alias {alias} from {path}')\n\n    if not path.exists():\n        logger.warning(f'path does not exist in oscal_read: {path}')\n        return None\n\n    obj: Dict[str, Any] = {}\n    try:\n        if content_type == FileContentType.YAML:\n            yaml = YAML(typ='safe')\n            fh = path.open('r', encoding=const.FILE_ENCODING)\n            obj = yaml.load(fh)\n            fh.close()\n        elif content_type == FileContentType.JSON:\n            obj = load_file(\n                path,\n                json_loads=cls.__config__.json_loads,\n            )\n    except Exception as e:\n        raise err.TrestleError(f'Error loading file {path} {str(e)}')\n    try:\n        if not len(obj) == 1:\n            raise err.TrestleError(\n                f'Invalid OSCAL file structure, oscal file '\n                f'does not have a single top level key wrapping it. It has {len(obj)} keys.'\n            )\n        parsed = cls.parse_obj(obj[alias])\n    except KeyError:\n        raise err.TrestleError(f'Provided oscal file does not have top level key key: {alias}')\n    except Exception as e:\n        raise err.TrestleError(f'Error parsing file {path} {str(e)}')\n\n    return parsed\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_serialize_json","title":"oscal_serialize_json(self, pretty=False, wrapped=True)","text":"

                                                                            Return an 'oscal wrapped' json object serialized in a compressed form as bytes.

                                                                            Parameters:

                                                                            Name Type Description Default pretty bool

                                                                            Whether or not to pretty-print json output or have in compressed form.

                                                                            False

                                                                            Returns:

                                                                            Type Description str

                                                                            Oscal model serialized to a json object including packaging inside of a single top level key.

                                                                            Source code in trestle/core/base_model.py
                                                                            def oscal_serialize_json(self, pretty: bool = False, wrapped: bool = True) -> str:\n\"\"\"\n    Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n    Args:\n        pretty: Whether or not to pretty-print json output or have in compressed form.\n    Returns:\n        Oscal model serialized to a json object including packaging inside of a single top level key.\n    \"\"\"\n    # This function is provided for backwards compatibility\n    return self.oscal_serialize_json_bytes(pretty, wrapped).decode(const.FILE_ENCODING)\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_serialize_json_bytes","title":"oscal_serialize_json_bytes(self, pretty=False, wrapped=True)","text":"

                                                                            Return an 'oscal wrapped' json object serialized in a compressed form as bytes.

                                                                            Parameters:

                                                                            Name Type Description Default pretty bool

                                                                            Whether or not to pretty-print json output or have in compressed form.

                                                                            False

                                                                            Returns:

                                                                            Type Description bytes

                                                                            Oscal model serialized to a json object including packaging inside of a single top level key.

                                                                            Source code in trestle/core/base_model.py
                                                                            def oscal_serialize_json_bytes(self, pretty: bool = False, wrapped: bool = True) -> bytes:\n\"\"\"\n    Return an 'oscal wrapped' json object serialized in a compressed form as bytes.\n\n    Args:\n        pretty: Whether or not to pretty-print json output or have in compressed form.\n    Returns:\n        Oscal model serialized to a json object including packaging inside of a single top level key.\n    \"\"\"\n    if wrapped:\n        odict = self.oscal_dict()\n    else:\n        odict = self.dict(by_alias=True, exclude_none=True)\n    if pretty:\n        return orjson.dumps(odict, default=self.__json_encoder__, option=orjson.OPT_INDENT_2)  # type: ignore\n    return orjson.dumps(odict, default=self.__json_encoder__)  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.oscal_write","title":"oscal_write(self, path)","text":"

                                                                            Write out a pydantic data model in an oscal friendly way.

                                                                            OSCAL schema mandates that top level elements are wrapped in a singular json/yaml field. This function handles both json and yaml output as well as formatting of the json.

                                                                            Parameters:

                                                                            Name Type Description Default path Path

                                                                            The output file location for the oscal object.

                                                                            required

                                                                            Exceptions:

                                                                            Type Description err.TrestleError

                                                                            If a unknown file extension is provided.

                                                                            Source code in trestle/core/base_model.py
                                                                            def oscal_write(self, path: pathlib.Path) -> None:\n\"\"\"\n    Write out a pydantic data model in an oscal friendly way.\n\n    OSCAL schema mandates that top level elements are wrapped in a singular\n    json/yaml field. This function handles both json and yaml output as well\n    as formatting of the json.\n\n    Args:\n        path: The output file location for the oscal object.\n\n    Raises:\n        err.TrestleError: If a unknown file extension is provided.\n    \"\"\"\n    content_type = FileContentType.to_content_type(path.suffix)\n    # The output will have \\r\\n newlines on windows and \\n newlines elsewhere\n\n    if content_type == FileContentType.YAML:\n        write_file = pathlib.Path(path).open('w', encoding=const.FILE_ENCODING)\n        yaml = YAML(typ='safe')\n        yaml.dump(yaml.load(self.oscal_serialize_json()), write_file)\n        write_file.flush()\n        write_file.close()\n    elif content_type == FileContentType.JSON:\n        write_file = pathlib.Path(path).open('wb')  # type: ignore\n        write_file.write(self.oscal_serialize_json_bytes(pretty=True))  # type: ignore\n        # Flush / close required (by experience) due to flushing issues in tests.\n        write_file.flush()\n        write_file.close()\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.OscalBaseModel.stripped_instance","title":"stripped_instance(self, stripped_fields=None, stripped_fields_aliases=None)","text":"

                                                                            Return a new model instance with the specified fields being stripped.

                                                                            Parameters:

                                                                            Name Type Description Default stripped_fields Optional[List[str]]

                                                                            The fields to be removed from the current data class.

                                                                            None stripped_fields_aliases Optional[List[str]]

                                                                            The fields to be removed from the current data class provided by alias.

                                                                            None

                                                                            Returns:

                                                                            Type Description OscalBaseModel

                                                                            The current datamodel with the fields provided removed in a derivate (run time created) data model.

                                                                            Exceptions:

                                                                            Type Description err.TrestleError

                                                                            If user provided both stripped_fields and stripped_field_aliases or neither.

                                                                            err.TrestleError

                                                                            If incorrect aliases or field names are provided.

                                                                            Source code in trestle/core/base_model.py
                                                                            def stripped_instance(\n    self,\n    stripped_fields: Optional[List[str]] = None,\n    stripped_fields_aliases: Optional[List[str]] = None\n) -> 'OscalBaseModel':\n\"\"\"Return a new model instance with the specified fields being stripped.\n\n    Args:\n        stripped_fields: The fields to be removed from the current data class.\n        stripped_fields_aliases: The fields to be removed from the current data class provided by alias.\n\n    Returns:\n        The current datamodel with the fields provided removed in a derivate (run time created) data model.\n\n    Raises:\n        err.TrestleError: If user provided both stripped_fields and stripped_field_aliases or neither.\n        err.TrestleError: If incorrect aliases or field names are provided.\n    \"\"\"\n    # stripped class type\n    stripped_class: Type[OscalBaseModel] = self.create_stripped_model_type(\n        stripped_fields=stripped_fields, stripped_fields_aliases=stripped_fields_aliases\n    )\n\n    # remaining values\n    remaining_values = {}\n    for field in self.__fields__.values():\n        if field.name in stripped_class.__fields__:\n            remaining_values[field.name] = self.__dict__[field.name]\n\n    # create stripped model instance\n    # TODO: Not sure if we can avoid type escapes here\n    stripped_instance = stripped_class(**remaining_values)\n\n    return stripped_instance\n
                                                                            "},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.base_model/#trestle.core.base_model.robust_datetime_serialization","title":"robust_datetime_serialization(input_dt)","text":"

                                                                            Return a nicely formatted string for in a format compatible with OSCAL specifications.

                                                                            Parameters:

                                                                            Name Type Description Default input_dt datetime

                                                                            Input datetime to convert to a string.

                                                                            required

                                                                            Returns:

                                                                            Type Description str

                                                                            String in isoformat to the millisecond enforcing that timezone offset is provided.

                                                                            Exceptions:

                                                                            Type Description TrestleError

                                                                            Error is raised if datetime object does not contain sufficient timezone information.

                                                                            Source code in trestle/core/base_model.py
                                                                            def robust_datetime_serialization(input_dt: datetime.datetime) -> str:\n\"\"\"Return a nicely formatted string for in a format compatible with OSCAL specifications.\n\n    Args:\n        input_dt: Input datetime to convert to a string.\n\n    Returns:\n        String in isoformat to the millisecond enforcing that timezone offset is provided.\n\n    Raises:\n        TrestleError: Error is raised if datetime object does not contain sufficient timezone information.\n    \"\"\"\n    # fail if the input datetime is not aware - ie it has no associated timezone\n    if input_dt.tzinfo is None:\n        raise err.TrestleError('Missing timezone in datetime')\n    if input_dt.tzinfo.utcoffset(input_dt) is None:\n        raise err.TrestleError('Missing utcoffset in datetime')\n\n    # use this leave in original timezone rather than utc\n    # return input_dt.astimezone().isoformat(timespec='milliseconds')  noqa: E800\n\n    # force it to be utc\n    return input_dt.astimezone(datetime.timezone.utc).isoformat(timespec='milliseconds')\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/","title":"catalog_api","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api","title":"trestle.core.catalog.catalog_api","text":"

                                                                            Main entrypoint to interact with catalog in memory.

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI","title":" CatalogAPI ","text":"

                                                                            Main entrypoint to interact with catalog in memory.

                                                                            Encapsulates all necessary functionality to manipulate, read and write the catalog and its markdown representation.

                                                                            Source code in trestle/core/catalog/catalog_api.py
                                                                            class CatalogAPI():\n\"\"\"\n    Main entrypoint to interact with catalog in memory.\n\n    Encapsulates all necessary functionality to manipulate, read\n    and write the catalog and its markdown representation.\n    \"\"\"\n\n    def __init__(self, catalog: Optional[cat.Catalog], context: Optional[ControlContext] = None):\n\"\"\"Initialize catalog api.\"\"\"\n        if not catalog:\n            # catalog assemble initializes with no catalog but may merge into an existing one later\n            logger.debug('No catalog was provided in CatalogAPI init, generating a new one.')\n            catalog = gens.generate_sample_model(cat.Catalog)\n        self._catalog = catalog\n        self._catalog_interface = CatalogInterface(self._catalog)\n        self._writer = CatalogWriter(self._catalog_interface)\n        self._reader = CatalogReader(self._catalog_interface)\n        self._merger = CatalogMerger(self._catalog_interface)\n        self._context = context\n\n    def update_context(self, context: ControlContext) -> None:\n\"\"\"Update current context.\"\"\"\n        if not context:\n            raise TrestleError('ControlContext cannot be empty.')\n        self._context = context\n\n    def write_catalog_as_markdown(self, label_as_key: bool = False) -> None:\n\"\"\"\n        Write out the catalog controls from dict as markdown files to the specified directory.\n\n        Args:\n            label_as_key: Whether to use label_as_key for part_id to label map\n\n        Returns:\n            None\n        \"\"\"\n        # create the directory in which to write the control markdown files\n        self._context.md_root.mkdir(exist_ok=True, parents=True)\n\n        part_id_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n        if self._context.purpose == ContextPurpose.PROFILE:\n            found_alters, _, _ = self.read_additional_content_from_md(label_as_key=True)\n            self._writer.write_catalog_as_profile_markdown(self._context, part_id_map, found_alters)\n        elif self._context.purpose == ContextPurpose.COMPONENT:\n            self._writer.write_catalog_as_component_markdown(self._context, part_id_map)\n        elif self._context.purpose == ContextPurpose.SSP:\n            self._writer.write_catalog_as_ssp_markdown(self._context, part_id_map)\n        else:\n            self._writer.write_catalog_as_catalog(self._context, part_id_map)\n\n        # prune any directories that have no markdown files\n        prune_empty_dirs(self._context.md_root, '*.md')\n\n    def read_catalog_from_markdown(self, markdown_dir: pathlib.Path, is_set_parameters: bool) -> cat.Catalog:\n\"\"\"Read catalog from markdown.\"\"\"\n        md_catalog = self._reader.read_catalog_from_markdown(markdown_dir, is_set_parameters)\n        md_catalog_interface = CatalogInterface(md_catalog)\n        if md_catalog_interface.get_count_of_controls_in_catalog(True) == 0:\n            raise TrestleError(f'No controls were loaded from markdown {markdown_dir}.  No catalog created.')\n\n        return md_catalog\n\n    def read_additional_content_from_md(self,\n                                        label_as_key: bool = False\n                                        ) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read additional content from markdown.\"\"\"\n        if not self._context:\n            raise TrestleError('Reading content from the markdown requires context to be initialized!')\n        label_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n        return self._reader.read_additional_content(\n            self._context.md_root,\n            self._context.required_sections,\n            label_map,\n            self._context.sections_dict,\n            self._context.to_markdown\n        )\n\n    def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"Merge one catalog into another.\"\"\"\n        return self._merger.merge_catalog(catalog, replace_params)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.__init__","title":"__init__(self, catalog, context=None) special","text":"

                                                                            Initialize catalog api.

                                                                            Source code in trestle/core/catalog/catalog_api.py
                                                                            def __init__(self, catalog: Optional[cat.Catalog], context: Optional[ControlContext] = None):\n\"\"\"Initialize catalog api.\"\"\"\n    if not catalog:\n        # catalog assemble initializes with no catalog but may merge into an existing one later\n        logger.debug('No catalog was provided in CatalogAPI init, generating a new one.')\n        catalog = gens.generate_sample_model(cat.Catalog)\n    self._catalog = catalog\n    self._catalog_interface = CatalogInterface(self._catalog)\n    self._writer = CatalogWriter(self._catalog_interface)\n    self._reader = CatalogReader(self._catalog_interface)\n    self._merger = CatalogMerger(self._catalog_interface)\n    self._context = context\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.merge_catalog","title":"merge_catalog(self, catalog, replace_params)","text":"

                                                                            Merge one catalog into another.

                                                                            Source code in trestle/core/catalog/catalog_api.py
                                                                            def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"Merge one catalog into another.\"\"\"\n    return self._merger.merge_catalog(catalog, replace_params)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.read_additional_content_from_md","title":"read_additional_content_from_md(self, label_as_key=False)","text":"

                                                                            Read additional content from markdown.

                                                                            Source code in trestle/core/catalog/catalog_api.py
                                                                            def read_additional_content_from_md(self,\n                                    label_as_key: bool = False\n                                    ) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read additional content from markdown.\"\"\"\n    if not self._context:\n        raise TrestleError('Reading content from the markdown requires context to be initialized!')\n    label_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n    return self._reader.read_additional_content(\n        self._context.md_root,\n        self._context.required_sections,\n        label_map,\n        self._context.sections_dict,\n        self._context.to_markdown\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.read_catalog_from_markdown","title":"read_catalog_from_markdown(self, markdown_dir, is_set_parameters)","text":"

                                                                            Read catalog from markdown.

                                                                            Source code in trestle/core/catalog/catalog_api.py
                                                                            def read_catalog_from_markdown(self, markdown_dir: pathlib.Path, is_set_parameters: bool) -> cat.Catalog:\n\"\"\"Read catalog from markdown.\"\"\"\n    md_catalog = self._reader.read_catalog_from_markdown(markdown_dir, is_set_parameters)\n    md_catalog_interface = CatalogInterface(md_catalog)\n    if md_catalog_interface.get_count_of_controls_in_catalog(True) == 0:\n        raise TrestleError(f'No controls were loaded from markdown {markdown_dir}.  No catalog created.')\n\n    return md_catalog\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.update_context","title":"update_context(self, context)","text":"

                                                                            Update current context.

                                                                            Source code in trestle/core/catalog/catalog_api.py
                                                                            def update_context(self, context: ControlContext) -> None:\n\"\"\"Update current context.\"\"\"\n    if not context:\n        raise TrestleError('ControlContext cannot be empty.')\n    self._context = context\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_api/#trestle.core.catalog.catalog_api.CatalogAPI.write_catalog_as_markdown","title":"write_catalog_as_markdown(self, label_as_key=False)","text":"

                                                                            Write out the catalog controls from dict as markdown files to the specified directory.

                                                                            Parameters:

                                                                            Name Type Description Default label_as_key bool

                                                                            Whether to use label_as_key for part_id to label map

                                                                            False

                                                                            Returns:

                                                                            Type Description None

                                                                            None

                                                                            Source code in trestle/core/catalog/catalog_api.py
                                                                            def write_catalog_as_markdown(self, label_as_key: bool = False) -> None:\n\"\"\"\n    Write out the catalog controls from dict as markdown files to the specified directory.\n\n    Args:\n        label_as_key: Whether to use label_as_key for part_id to label map\n\n    Returns:\n        None\n    \"\"\"\n    # create the directory in which to write the control markdown files\n    self._context.md_root.mkdir(exist_ok=True, parents=True)\n\n    part_id_map = self._catalog_interface.get_statement_part_id_map(label_as_key=label_as_key)\n\n    if self._context.purpose == ContextPurpose.PROFILE:\n        found_alters, _, _ = self.read_additional_content_from_md(label_as_key=True)\n        self._writer.write_catalog_as_profile_markdown(self._context, part_id_map, found_alters)\n    elif self._context.purpose == ContextPurpose.COMPONENT:\n        self._writer.write_catalog_as_component_markdown(self._context, part_id_map)\n    elif self._context.purpose == ContextPurpose.SSP:\n        self._writer.write_catalog_as_ssp_markdown(self._context, part_id_map)\n    else:\n        self._writer.write_catalog_as_catalog(self._context, part_id_map)\n\n    # prune any directories that have no markdown files\n    prune_empty_dirs(self._context.md_root, '*.md')\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/","title":"catalog_interface","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface","title":"trestle.core.catalog.catalog_interface","text":"

                                                                            Provide interface to catalog allowing queries and operations at control level.

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface","title":" CatalogInterface ","text":"

                                                                            Interface to query and modify catalog contents.

                                                                            The catalog is contained in two separate forms: As an actual OSCAL catalog, and as a separate dict providing direct lookup of a control by id.

                                                                            The two representations should be converted as needed using provided routines: dict -> cat: update_catalog_controls cat -> dict: _create_control_dict

                                                                            In normal use the dict is created by the CatalogInterface constructor, changes are then made to controls in the dict, then the catalog controls are updated by pulling from the dict back into the catalog.

                                                                            This class does no direct file i/o. i/o is performed via ControlIO.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            class CatalogInterface():\n\"\"\"\n    Interface to query and modify catalog contents.\n\n    The catalog is contained in two separate forms:  As an actual OSCAL catalog,\n    and as a separate dict providing direct lookup of a control by id.\n\n    The two representations should be converted as needed using provided routines:\n    dict -> cat: update_catalog_controls\n    cat -> dict: _create_control_dict\n\n    In normal use the dict is created by the CatalogInterface constructor,\n    changes are then made to controls in the dict,\n    then the catalog controls are updated by pulling from the dict back into the catalog.\n\n    This class does no direct file i/o.  i/o is performed via ControlIO.\n    \"\"\"\n\n    @dataclass\n    class ControlHandle:\n\"\"\"Convenience class for handling controls as members of a group.\n\n        group_id: id of parent group or '' if not in a group\n        group_title: title of the group\n        group_class: class of the group\n        path: path of parent groups leading to this control - without the final control_id, or [''] if in cat list\n        important to remember that controls may not be in a group and are directly attached to cat\n        control: the control itself\n        \"\"\"\n\n        group_id: str\n        group_title: Optional[str]\n        group_class: Optional[str]\n        group_path: List[str]\n        control_path: List[str]\n        control: cat.Control\n\n    def __init__(self, catalog: Optional[cat.Catalog] = None) -> None:\n\"\"\"Initialize the interface with the catalog.\"\"\"\n        self._catalog = catalog\n        self._param_control_map: Dict[str, str] = {}\n        self._generate_group_index: int = 0\n        self._control_dict = self._create_control_dict() if catalog else None\n        self.loose_param_dict: Dict[str, common.Parameter] = {param.id: param\n                                                              for param in as_list(catalog.params)} if catalog else {}\n        # map control id to CompDict\n        self._control_comp_dicts: Dict[str, CompDict] = {}\n        # map control id to dict containing set parameters by component\n        self._control_comp_set_params: Dict[str, Dict[str, comp.SetParameter]] = {}\n\n    def add_comp_info(self, control_id: str, comp_name: str, label: str, comp_info: ComponentImpInfo) -> None:\n\"\"\"Add comp_info for a control.\"\"\"\n        deep_set(self._control_comp_dicts, [control_id, comp_name, label], comp_info)\n\n    def get_comp_info(self, control_id: str) -> CompDict:\n\"\"\"Get comp_dict for this control.\"\"\"\n        return self._control_comp_dicts.get(control_id, {})\n\n    def clear_comp_dicts(self) -> None:\n\"\"\"Clear the control component dicts.\"\"\"\n        self._control_comp_dicts = {}\n\n    def add_comp_set_param(self, control_id: str, comp_name: str, set_param: comp.SetParameter) -> None:\n\"\"\"Add component setparam for control with overwrite.\"\"\"\n        deep_append(self._control_comp_set_params, [control_id, comp_name], set_param)\n\n    def get_control_comp_set_params(self, control_id: str) -> Dict[str, List[comp.SetParameter]]:\n\"\"\"Get dict of setparams list per component.\"\"\"\n        return self._control_comp_set_params.get(control_id, {})\n\n    def clear_set_params(self) -> None:\n\"\"\"Clear the control set params.\"\"\"\n        self._control_comp_set_params = {}\n\n    def _generate_group_id(self, group: cat.Group) -> str:\n\"\"\"Generate sequential group ids.\"\"\"\n        group_id = f'trestle_group_{self._generate_group_index:04d}'\n        self._generate_group_index += 1\n        logger.warning(f'Group titled \"{group.title}\" has no id and has been assigned id: {group_id}')\n        return group_id\n\n    def _add_params_to_map(self, control: cat.Control) -> None:\n        # this does not need to recurse because it is called for each control in the catalog\n        for param in as_list(control.params):\n            if param.id in self._param_control_map:\n                logger.warning(\n                    f'Duplicate param id {param.id} in control {control.id} and {self._param_control_map[param.id]}.'\n                )\n            self._param_control_map[param.id] = control.id\n\n    def _add_sub_controls(\n        self, control_handle: ControlHandle, control_dict: Dict[str, ControlHandle], path: List[str]\n    ) -> None:\n\"\"\"\n        Get all controls contained in this control and add it to the growing control dict.\n\n        Add all its sub-controls to the dict recursively.\n        The path does not change because only groups are in the path, and controls cannot contain groups.\n        \"\"\"\n        if control_handle.control.controls:\n            group_id = control_handle.group_id\n            group_title = control_handle.group_title\n            group_class = control_handle.group_class\n            group_path = control_handle.group_path\n            control_path = path[:]\n            control_path.append(control_handle.control.id)\n            for sub_control in control_handle.control.controls:\n                control_handle = CatalogInterface.ControlHandle(\n                    group_id=group_id,\n                    group_title=group_title,\n                    group_class=group_class,\n                    group_path=group_path,\n                    control_path=control_path,\n                    control=sub_control\n                )\n                control_dict[sub_control.id] = control_handle\n                self._add_sub_controls(control_handle, control_dict, control_path)\n\n    def _add_group_controls(self, group: cat.Group, control_dict: Dict[str, ControlHandle], path: List[str]) -> None:\n\"\"\"Add all controls in the group recursively, including sub groups and sub controls.\"\"\"\n        group.id = self._generate_group_id(group) if group.id is None else group.id\n        if group.controls is not None:\n            group_path = path[:]\n            if not group_path or group_path[-1] != group.id:\n                group_path.append(group.id)\n            for control in group.controls:\n                control_handle = CatalogInterface.ControlHandle(\n                    group_id=group.id,\n                    group_title=group.title,\n                    group_class=group.class_,\n                    control=control,\n                    group_path=group_path,\n                    control_path=group_path\n                )\n                control_dict[control.id] = control_handle\n                self._add_sub_controls(control_handle, control_dict, group_path)\n        if group.groups is not None:\n            group_path = path[:]\n            group_path.append(group.id)\n            for sub_group in group.groups:\n                new_path = group_path[:]\n                sub_group.id = self._generate_group_id(sub_group) if sub_group.id is None else sub_group.id\n                new_path.append(sub_group.id)\n                self._add_group_controls(sub_group, control_dict, new_path)\n\n    def _create_control_dict(self) -> Dict[str, ControlHandle]:\n        control_dict: Dict[str, CatalogInterface.ControlHandle] = {}\n        # add controls by group\n        if self._catalog.groups is not None:\n            for group in self._catalog.groups:\n                self._add_group_controls(group, control_dict, [])\n        # now add controls not in a group, if any\n        if self._catalog.controls is not None:\n            group_path = ['']\n            for control in self._catalog.controls:\n                control_handle = CatalogInterface.ControlHandle(\n                    group_id='',\n                    group_title='',\n                    group_class=const.MODEL_TYPE_CATALOG,\n                    control=control,\n                    group_path=group_path,\n                    control_path=group_path\n                )\n                control_dict[control.id] = control_handle\n                self._add_sub_controls(control_handle, control_dict, group_path)\n        for handle in control_dict.values():\n            self._add_params_to_map(handle.control)\n        return control_dict\n\n    @staticmethod\n    def _get_all_controls_in_list(controls: List[cat.Control], recurse: bool) -> List[cat.Control]:\n\"\"\"Get all controls in a list with optional recursion for sub controls.\"\"\"\n        new_list: List[cat.Control] = []\n        for control in controls:\n            new_list.append(control)\n            if recurse and control.controls:\n                new_list.extend(CatalogInterface._get_all_controls_in_list(control.controls, recurse))\n        return new_list\n\n    @staticmethod\n    def _get_all_controls_in_group(group: cat.Group, recurse: bool) -> List[cat.Control]:\n\"\"\"\n        Create a list of all controls in this group.\n\n        recurse specifies to recurse within controls, but groups are always recursed\n        \"\"\"\n        controls: List[cat.Control] = []\n        if group.controls:\n            controls.extend(CatalogInterface._get_all_controls_in_list(group.controls, recurse))\n        for sub_group in as_list(group.groups):\n            controls.extend(CatalogInterface._get_all_controls_in_group(sub_group, recurse))\n        return controls\n\n    def get_sorted_controls_in_group(self, group_id: str) -> List[cat.Control]:\n\"\"\"Get the list of controls in a group sorted by the control sort-id.\"\"\"\n        controls: List[cat.Control] = []\n        for control in self.get_all_controls_from_dict():\n            grp_id, _, _ = self.get_group_info_by_control(control.id)\n            if grp_id == group_id:\n                controls.append(control)\n        return sorted(controls, key=lambda control: ControlInterface.get_sort_id(control))\n\n    def get_dependent_control_ids(self, control_id: str) -> List[str]:\n\"\"\"Find all child ids of this control from the dict with recursion.\"\"\"\n        children: List[str] = []\n        control = self.get_control(control_id)\n        if control:\n            new_controls = self._get_all_controls_in_list(as_list(control.controls), True)\n            children.extend([con.id for con in new_controls])\n        return children\n\n    def get_control_ids(self) -> List[str]:\n\"\"\"Get all control ids from the control dict.\"\"\"\n        return self._control_dict.keys()\n\n    def get_control(self, control_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from the control dict with this id.\"\"\"\n        return None if control_id not in self._control_dict else self._control_dict[control_id].control\n\n    @staticmethod\n    def get_control_ids_from_catalog(catalog: cat.Catalog) -> List[str]:\n\"\"\"\n        Get all control ids from a catalog.\n\n        This is intended to provide a quick list of all controls in a catalog without the expense of building the\n        control dict.  So, if repeated queries are made into a catalog, it is worth instantiating a CatalogInterface\n        and associated control dict.  Otherwise just use this to get a list of all controls.\n\n        This function is needed within the CatalogInterface in order to determine if new controls have been added\n        to the dict and need to be inserted in the actual catalog during update.\n        \"\"\"\n        controls = CatalogInterface._get_all_controls_in_list(as_list(catalog.controls), True)\n        id_list = [control.id for control in controls]\n        for group in as_list(catalog.groups):\n            controls = CatalogInterface._get_all_controls_in_group(group, True)\n            id_list.extend([control.id for control in as_list(controls)])\n        return id_list\n\n    def get_control_by_param_id(self, param_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from catalog that has this param id using the dict.\"\"\"\n        if param_id in self._param_control_map:\n            return self.get_control(self._param_control_map[param_id])\n        return None\n\n    def get_control_id_and_status(self, control_name: str) -> Tuple[str, str]:\n\"\"\"\n        Get the control id and status using the control name.\n\n        Returns empty string if status not found.\n        \"\"\"\n        for control in self.get_all_controls_from_dict():\n            if ControlInterface.get_label(control).strip().lower() == control_name.strip().lower():\n                status = ControlInterface.get_prop(control, 'status')\n                return control.id, status\n        return '', ''\n\n    def get_catalog_title(self) -> str:\n\"\"\"Get the title of the catalog.\"\"\"\n        return self._catalog.metadata.title\n\n    def get_statement_part_id_map(self, label_as_key: bool) -> Dict[str, Dict[str, str]]:\n\"\"\"Create mapping of label to part_id for top level parts in statement of all controls.\"\"\"\n        id_map = {}\n        for control in self.get_all_controls_from_catalog(True):\n            statement_part = get_item_from_list(control.parts, const.STATEMENT, lambda p: p.name)\n            if not statement_part:\n                continue\n            id_dict: Dict[str, str] = {}\n            for sub_part in as_list(statement_part.parts):\n                label = ControlInterface.get_label(sub_part)\n                # skip add to map for empty label\n                if not label:\n                    continue\n                if label_as_key:\n                    id_dict[label] = sub_part.id\n                else:\n                    id_dict[sub_part.id] = label\n            if id_dict:\n                id_map[control.id] = id_dict\n        return id_map\n\n    @staticmethod\n    def _get_statement_sub_parts(part: common.Part, indent: int) -> List[Dict[str, str]]:\n        items = []\n        # this may be '' if no label\n        label = ControlInterface.get_label(part)\n        prose = '' if part.prose is None else part.prose\n        items.append({'indent': indent, 'label': label, 'prose': prose})\n        for prt in as_filtered_list(part.parts, lambda p: p.name == const.ITEM):\n            items.extend(CatalogInterface._get_statement_sub_parts(prt, indent + 1))\n        return items\n\n    def get_statement_parts(self, control_id: str) -> List[Dict[str, str]]:\n\"\"\"Get list of statement parts as dicts with indentation, label and prose.\"\"\"\n        items = []\n        control = self.get_control(control_id)\n\n        # control may have no statement or parts\n        # but if statement present it is first part\n        if control is None:\n            logger.warning(f'No control found for id {control_id}')\n        elif control.parts:\n            part = control.parts[0]\n            if part.name == 'statement':\n                items.extend(CatalogInterface._get_statement_sub_parts(part, 0))\n            else:\n                logger.warning(f'Control {control_id} has parts but first part name is {part.name} - not statement')\n        return items\n\n    def get_control_part_prose(self, control_id: str, part_name: str) -> str:\n\"\"\"\n        Get the prose for a named part in the control.\n\n        Args:\n            control_id: id of the control\n            part_name: name of the part\n\n        Returns:\n            Single string concatenating prose from all parts and sub-parts in control with that name.\n        \"\"\"\n        control = self.get_control(control_id)\n        return ControlInterface.get_part_prose(control, part_name)\n\n    def get_all_controls_from_catalog(self, recurse: bool) -> Iterator[cat.Control]:\n\"\"\"\n        Yield all controls from the actual catalog by group including optional sub controls.\n\n        Args:\n            recurse: Whether to recurse within controls, but groups are always recursed\n\n        Returns:\n            iterator of the controls in the catalog\n\n        Notes:\n            This follows the actual structure of the catalog and groups\n        \"\"\"\n        if self._catalog.groups:\n            for group in self._catalog.groups:\n                controls = self._get_all_controls_in_group(group, recurse)\n                for control in controls:\n                    yield control\n        if self._catalog.controls:\n            cat_controls = self._get_all_controls_in_list(self._catalog.controls, recurse)\n            for control in cat_controls:\n                yield control\n\n    def get_all_controls_from_dict(self) -> List[cat.Control]:\n\"\"\"Yield individual controls from the dict.\"\"\"\n        return [handle.control for handle in self._control_dict.values()]\n\n    def get_count_of_controls_in_dict(self) -> int:\n\"\"\"Find number of controls in the dict.\"\"\"\n        return len(self._control_dict.keys())\n\n    def get_count_of_controls_in_catalog(self, recurse: bool) -> int:\n\"\"\"Get count of controls from the actual catalog including optional sub controls.\"\"\"\n        return len(list(self.get_all_controls_from_catalog(recurse)))\n\n    def get_group_ids(self) -> List[str]:\n\"\"\"Get all the group id's as a list of sorted strings.\"\"\"\n        return sorted(filter(lambda id_: id_, list({control.group_id for control in self._control_dict.values()})))\n\n    def get_all_groups_from_catalog(self) -> List[cat.Group]:\n\"\"\"\n        Retrieve all groups in the catalog sorted by group_id.\n\n        This ignores controls that are direct children of the catalog.\n        \"\"\"\n        groups: List[cat.Group] = []\n        if self._catalog.groups:\n            for my_group in self._catalog.groups:\n                for res in CatalogInterface._get_groups_from_group(my_group):\n                    groups.append(res)\n        return sorted(groups, key=lambda group: group.id)\n\n    def get_statement_label_if_exists(self, control_id: str,\n                                      statement_id: str) -> Tuple[Optional[str], Optional[common.Part]]:\n\"\"\"Get statement label if available.\"\"\"\n\n        def does_part_exists(part: common.Part) -> bool:\n            does_match = False\n            if part.name and part.name in {const.STATEMENT, const.ITEM} and part.id == statement_id:\n                does_match = True\n            return does_match\n\n        control = self.get_control(control_id)\n        if not control:\n            return '', None\n        label = None\n        found_part = None\n        if control.parts:\n            for part in as_list(control.parts):\n                # Performance OSCAL assumption, ids are nested so recurse only if prefix\n                if part.id and statement_id.startswith(part.id):\n                    part = self.find_part_with_condition(part, does_part_exists)\n                    if part:\n                        label = ControlInterface.get_label(part)\n                        found_part = part\n                        break\n\n        return label, found_part\n\n    def find_part_with_condition(self, part: common.Part, condition: Callable) -> Optional[common.Part]:\n\"\"\"Traverse part and find subpart that satisfies given condition.\"\"\"\n        if condition(part):\n            # Part that satisfies the condition is found.\n            return part\n        else:\n            if part.parts:\n                for subpart in part.parts:\n                    found_part = self.find_part_with_condition(subpart, condition)\n                    if found_part:\n                        return found_part\n\n        return None\n\n    def delete_withdrawn_controls(self) -> None:\n\"\"\"Delete all withdrawn controls from the catalog.\"\"\"\n        delete_list = []\n        for control in self.get_all_controls_from_dict():\n            if ControlInterface.is_withdrawn(control):\n                delete_list.append(control.id)\n        for id_ in delete_list:\n            self.delete_control(id_)\n\n    @staticmethod\n    def _get_groups_from_group(group: cat.Group) -> Iterator[cat.Group]:\n        yield group\n        if group.groups:\n            for new_group in group.groups:\n                for res in CatalogInterface._get_groups_from_group(new_group):\n                    yield res\n\n    def get_group_info_by_control(self, control_id: str) -> Tuple[str, str, str]:\n\"\"\"Get the group_id, title, class for this control from the dict.\"\"\"\n        return (\n            '' if self._control_dict is None else self._control_dict[control_id].group_id,\n            '' if self._control_dict is None else self._control_dict[control_id].group_title,\n            '' if self._control_dict is None else self._control_dict[control_id].group_class\n        )\n\n    def get_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path into the markdown directory for this control based only on the groups.\"\"\"\n        return self._control_dict[control_id].group_path\n\n    def get_control_file_path(self, md_root: pathlib.Path, control_id: str) -> Optional[pathlib.Path]:\n\"\"\"Get the path to the control from the given root.\"\"\"\n        if control_id not in self._control_dict:\n            return None\n        path = md_root\n        for item in self.get_control_path(control_id):\n            path = path / item\n        return path / f'{control_id}.md'\n\n    def get_full_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path to the control including groups and sub-controls.\"\"\"\n        return self._control_dict[control_id].control_path\n\n    def replace_control(self, control: cat.Control) -> None:\n\"\"\"\n        Replace the control in the control_dict.\n\n        This only replaces the parent control and not its children.\n        \"\"\"\n        self._control_dict[control.id].control = control\n\n    def delete_control(self, control_id: str) -> None:\n\"\"\"\n        Delete the control from the control_dict based on id.\n\n        Delete all its dependent children also.\n        \"\"\"\n        control = self.get_control(control_id)\n        if control:\n            for sub_control_id in self.get_dependent_control_ids(control.id):\n                self._control_dict.pop(sub_control_id, None)\n            self._control_dict.pop(control_id, None)\n\n    def get_catalog(self, update=True) -> cat.Catalog:\n\"\"\"Safe method to get catalog after forced update from catalog dict.\"\"\"\n        if update:\n            self.update_catalog_controls()\n        return self._catalog\n\n    def _update_all_controls_in_list(self, controls: List[cat.Control]) -> List[cat.Control]:\n\"\"\"\n        Given a list of controls, create fresh list pulled from the control dict.\n\n        Args:\n            controls: a list of controls in the original catalog\n\n        Returns:\n            The new list of updated controls, possibly with some missing if they have been removed from the dict.\n            Children are inserted as needed into parent controls.\n        \"\"\"\n        new_list: List[cat.Control] = []\n        for control in controls:\n            # first update the control itself by getting it from the dict\n            new_control = self.get_control(control.id)\n            if new_control:\n                # this overrides any sub controls in the control itself\n                # any added sub-controls should add to the skipped list\n                new_control.controls = self._update_all_controls_in_list(as_list(control.controls))\n                new_control.controls = none_if_empty(new_control.controls)\n                new_list.append(new_control)\n        return new_list\n\n    def _update_all_controls_in_group(self, group: cat.Group) -> None:\n\"\"\"Given a group of controls, create fresh version pulled from the control dict.\"\"\"\n        group.controls = self._update_all_controls_in_list(as_list(group.controls))\n        group.controls = none_if_empty(group.controls)\n        new_groups: List[cat.Group] = []\n        for sub_group in as_list(group.groups):\n            self._update_all_controls_in_group(sub_group)\n            new_groups.append(sub_group)\n        group.groups = none_if_empty(new_groups)\n\n    def _insert_control_in_catalog(self, control_handle: ControlHandle) -> None:\n\"\"\"Insert the control into the catalog based on its path.\"\"\"\n        path = control_handle.group_path\n        node = self._catalog\n        if path[0] != '':\n            for group_id in path:\n                found_group = None\n                for group in as_list(node.groups):\n                    if group.id == group_id:\n                        found_group = group\n                        break\n                if found_group:\n                    node = found_group\n                else:\n                    raise TrestleError(f'No controls found in catalog for group {group.id}')\n            node.title = control_handle.group_title\n            node.class_ = control_handle.group_class\n        node.controls = delete_item_from_list(\n            as_list(node.controls), control_handle.control.id, lambda control: control.id\n        )\n        node.controls.append(control_handle.control)\n        node.controls = none_if_empty(sorted(node.controls, key=lambda control: ControlInterface.get_sort_id(control)))\n\n    def update_catalog_controls(self) -> None:\n\"\"\"\n        Update the actual catalog by pulling fresh controls from the dict.\n\n        During assembly, controls may be added, but not children of controls.\n        New groups may not be added.\n        A control containing controls cannot be added.  Controls containing controls are only available if\n        the parent catalog was loaded from json.\n        \"\"\"\n        # first go through the catalog and pull existing controls from the dict\n        for group in as_list(self._catalog.groups):\n            self._update_all_controls_in_group(group)\n\n        new_list = []\n        for control in as_list(self._catalog.controls):\n            new_control = self.get_control(control.id)\n            new_control.controls = self._update_all_controls_in_list(as_list(control.controls))\n            new_control.controls = none_if_empty(new_control.controls)\n            new_list.append(new_control)\n        self._catalog.controls = none_if_empty(new_list)\n\n        # now add any new controls that are discovered in the dict\n        ids_in_catalog = CatalogInterface.get_control_ids_from_catalog(self._catalog)\n        for control_handle in self._control_dict.values():\n            if control_handle.control.id not in ids_in_catalog:\n                self._insert_control_in_catalog(control_handle)\n\n        self._catalog.params = none_if_empty(list(self.loose_param_dict.values()))\n\n    def _find_string_in_part(self, control_id: str, part: common.Part, seek_str: str) -> List[str]:\n        hits: List[str] = []\n        if part.prose and part.prose.find(seek_str) >= 0:\n            hits.append((control_id, part.prose))\n        if part.parts:\n            for sub_part in part.parts:\n                hits.extend(self._find_string_in_part(control_id, sub_part, seek_str))\n        return hits\n\n    def find_string_in_control(self, control: cat.Control, seek_str: str) -> List[Tuple[str, str]]:\n\"\"\"Find all instances of this string in prose of control.\"\"\"\n        hits: List[Tuple[str, str]] = []\n        if control.parts:\n            for part in control.parts:\n                hits.extend(self._find_string_in_part(control.id, part, seek_str))\n        return hits\n\n    @staticmethod\n    def _get_full_profile_param_dict(profile: Optional[prof.Profile]) -> Dict[str, common.Parameter]:\n\"\"\"Get the full mapping of param_id to modified value for this profiles set_params.\"\"\"\n        set_param_dict: Dict[str, common.Parameter] = {}\n        if profile and profile.modify:\n            for set_param in as_list(profile.modify.set_parameters):\n                param = ControlInterface.setparam_to_param(set_param.param_id, set_param)\n                set_param_dict[set_param.param_id] = param\n        return set_param_dict\n\n    @staticmethod\n    def _get_profile_param_dict(\n        control: cat.Control, profile_param_dict: Dict[str, common.Parameter], values_only: bool\n    ) -> Dict[str, common.Parameter]:\n\"\"\"\n        Get the dict of params for this control including possible overrides made by the profile modifications.\n\n        Args:\n            control: The control being queried\n            profile_param_dict: The full dict of params and modified values made by the profile\n\n        Returns:\n            mapping of param ids to their final parameter states after possible modify by the profile setparameters\n        \"\"\"\n        # get the mapping of param_id's to params for this control, excluding those with no value set\n        param_dict = ControlInterface.get_control_param_dict(control, values_only)\n        for key in param_dict.keys():\n            if key in profile_param_dict:\n                param_dict[key] = profile_param_dict[key]\n        return param_dict\n\n    def _get_full_param_dict(self) -> Dict[str, common.Parameter]:\n        param_dict: Dict[str, common.Parameter] = {}\n        # build the full mapping of params to values from the catalog interface\n        for control in self.get_all_controls_from_dict():\n            param_dict.update(ControlInterface.get_control_param_dict(control, False))\n        return param_dict\n\n    def _change_prose_with_param_values(\n        self,\n        param_format,\n        param_rep,\n        show_value_warnings: bool,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Go through all controls and change prose based on param values.\"\"\"\n        param_dict = self._get_full_param_dict()\n        # insert param values into prose of all controls\n        for control in self.get_all_controls_from_dict():\n            ControlInterface.replace_control_prose(\n                control,\n                param_dict,\n                param_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n\n    @staticmethod\n    def _get_display_name_and_ns(param: common.Parameter) -> Tuple[Optional[str], Optional[str]]:\n        for prop in as_list(param.props):\n            if prop.name == const.DISPLAY_NAME:\n                ns = str(prop.ns) if prop.ns else None\n                return prop.value, ns\n        return None, None\n\n    @staticmethod\n    def _get_param_value_origin_and_ns(param: common.Parameter) -> Tuple[Optional[str], Optional[str]]:\n        for prop in as_list(param.props):\n            if prop.name == const.PARAM_VALUE_ORIGIN:\n                ns = str(prop.ns) if prop.ns else None\n                return prop.value, ns\n        return None, None\n\n    @staticmethod\n    def _prune_controls(md_path: pathlib.Path, written_controls: Set[str]) -> List[str]:\n\"\"\"Search directory and remove any controls that were not written out.\"\"\"\n        deleted_controls = []\n        for control_file in md_path.rglob('*.md'):\n            if control_file.stem not in written_controls:\n                logger.debug(\n                    f'Existing control markdown {control_file} deleted since it was not written out during generate'\n                )  # noqa E501\n                control_file.unlink()\n                deleted_controls.append(control_file.stem)\n        return sorted(deleted_controls)\n\n    def _extend_rules_param_list(\n        self, control_id: str, header: Dict[str, Any], param_id_rule_name_map: Dict[str, str]\n    ) -> None:\n\"\"\"Go through all set_params and put in rules param list if name matches.\"\"\"\n        control_comp_set_params = {}\n        rules_set_params = {}\n        all_set_params = self.get_control_comp_set_params(control_id)\n        for comp_name, param_list in all_set_params.items():\n            for param in param_list:\n                param_vals = none_if_empty(as_list(param.values))\n                rule_name = deep_get(param_id_rule_name_map, [comp_name, param.param_id], None)\n                if rule_name:\n                    param_dict = {'name': param.param_id}\n                    if param_vals:\n                        param_dict['values'] = param_vals\n                    deep_append(rules_set_params, [comp_name], param_dict)\n        set_or_pop(header, const.COMP_DEF_RULES_PARAM_VALS_TAG, rules_set_params)\n        set_or_pop(header, const.SET_PARAMS_TAG, control_comp_set_params)\n\n    def _get_control_memory_info(self, control_id: str, context: ControlContext) -> Tuple[Dict[str, Any], CompDict]:\n\"\"\"Build the rule info for the control into the header.\"\"\"\n        header = {}\n        rule_names_list: List[str] = []\n        comp_dict = self.get_comp_info(control_id)\n        # find the rule names that are needed by the control\n        for _, value in comp_dict.items():\n            for comp_info in value.values():\n                rule_names_list.extend(as_list(comp_info.rules))\n        if rule_names_list:\n            header_rules_dict = {}\n            rule_ids = {}\n            param_id_rule_name_map = {}\n            rule_id_rule_name_map = {}\n            # only include rules needed by control in the header\n            for comp_name, rules_dict in context.rules_dict.items():\n                for rule_id, rule_dict in rules_dict.items():\n                    if rule_dict['name'] in rule_names_list:\n                        deep_append(rule_ids, [comp_name], rule_id)\n                        deep_append(header_rules_dict, [comp_name], rule_dict)\n                        deep_set(rule_id_rule_name_map, [comp_name, rule_id], rule_dict['name'])\n            set_or_pop(header, const.COMP_DEF_RULES_TAG, header_rules_dict)\n            rules_params = {}\n            rules_param_names = []\n            for comp_name, rules_params_dict in as_dict(context.rules_params_dict).items():\n                for rule_id, rules_parameters in rules_params_dict.items():\n                    if rule_id in rule_ids.get(comp_name, []):\n                        for rule_parameter in rules_parameters:\n                            param_name = rule_parameter['name']\n                            rules_param_names.append(param_name)\n                            rule_parameter[const.HEADER_RULE_ID] = rule_id_rule_name_map[comp_name].get(rule_id, None)\n                            deep_append(rules_params, [comp_name], rule_parameter)\n                            deep_set(\n                                param_id_rule_name_map, [comp_name, rule_parameter['name']],\n                                rule_id_rule_name_map[comp_name][rule_id]\n                            )\n            set_or_pop(header, const.RULES_PARAMS_TAG, rules_params)\n\n            self._extend_rules_param_list(control_id, header, param_id_rule_name_map)\n\n        return header, comp_dict\n\n    @staticmethod\n    def _get_group_ids_and_dirs(md_path: pathlib.Path) -> Dict[str, pathlib.Path]:\n\"\"\"\n        Create a sorted map of group id to group dir that is ordered by group id.\n\n        This includes '' as the root group id.\n        \"\"\"\n        # manually insert the top dir as group ''\n        id_map: Dict[str, pathlib.Path] = {'': md_path}\n        for gdir in md_path.rglob('*'):\n            if gdir.is_dir():\n                dir_name = gdir.parts[-1]\n                id_map[dir_name] = gdir\n        # rebuild the dict by inserting items in manner sorted by key\n        sorted_id_map: Dict[str, pathlib.Path] = {}\n        for key in sorted(id_map):\n            sorted_id_map[key] = id_map[key]\n        return sorted_id_map\n\n    def get_sections(self) -> List[str]:\n\"\"\"Get the available sections by a full index of all controls.\"\"\"\n        return list(\n            {\n                part.name\n                for control_handle in self._control_dict.values()\n                for part in as_list(control_handle.control.parts)\n                if part.name != const.STATEMENT\n            }\n        )\n\n    def _find_control_in_group(self, group_id: str) -> Tuple[str, ControlHandle]:\n\"\"\"\n        Find a representative control for this group and its control handle.\n\n        This is a simple way to get group info (title etc.) given only group id.\n        It is not intended for high performance loops.  Use only as needed.\n        \"\"\"\n        for control_id, control_handle in self._control_dict.items():\n            if control_handle.group_id == group_id:\n                return control_id, control_handle\n        raise TrestleError(f'No controls found for group {group_id}')\n\n    def _add_control_imp_comp_info(\n        self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]], comp_rules_props: List[common.Property]\n    ) -> None:\n\"\"\"Add component info to the impreqs of the control implementation based on applied rules.\"\"\"\n        control_imp_rules_dict, control_imp_rules_params_dict, ci_rules_props = ControlInterface.get_rules_and_params_dict_from_item(context.control_implementation)  # noqa E501\n        context.rules_dict[context.comp_name].update(control_imp_rules_dict)\n        comp_rules_params_dict = context.rules_params_dict.get(context.comp_name, {})\n        comp_rules_params_dict.update(control_imp_rules_params_dict)\n        context.rules_params_dict[context.comp_name] = comp_rules_params_dict\n        ci_set_params = ControlInterface.get_set_params_from_item(context.control_implementation)\n        catalog_control_ids = self.get_control_ids()\n        for imp_req in as_list(context.control_implementation.implemented_requirements):\n            if imp_req.control_id not in catalog_control_ids:\n                logger.warning(\n                    f'Component {context.component.title} references control {imp_req.control_id} not in profile.'\n                )\n            control_part_id_map = part_id_map.get(imp_req.control_id, {})\n            # find if any rules apply to this control, including in statements\n            control_rules, statement_rules, ir_props = ControlInterface.get_rule_list_for_imp_req(imp_req)\n            rule_props = comp_rules_props[:]\n            rule_props.extend(ci_rules_props)\n            rule_props.extend(ir_props)\n            rule_props = ControlInterface.clean_props(rule_props, remove_imp_status=False)\n            if control_rules:\n                status = ControlInterface.get_status_from_props(imp_req)\n                final_props = ControlInterface.cull_props_by_rules(rule_props, control_rules)\n                comp_info = ComponentImpInfo(imp_req.description, control_rules, final_props, status)\n                self.add_comp_info(imp_req.control_id, context.comp_name, '', comp_info)\n            set_params = copy.deepcopy(ci_set_params)\n            set_params.update(ControlInterface.get_set_params_from_item(imp_req))\n            for set_param in set_params.values():\n                # add to control_comp_set_params dict\n                self.add_comp_set_param(imp_req.control_id, context.comp_name, set_param)\n            for statement in as_list(imp_req.statements):\n                rule_list, stat_props = ControlInterface.get_rule_list_for_item(statement)\n                if rule_list:\n                    status = ControlInterface.get_status_from_props(statement)\n                    if statement.statement_id not in control_part_id_map:\n                        label = statement.statement_id\n                        logger.warning(\n                            f'No statement label found for statement id {label}.  Defaulting to {label}.'  # noqa E501\n                        )\n                    else:\n                        label = control_part_id_map[statement.statement_id]\n                    all_props = rule_props[:]\n                    all_props.extend(stat_props)\n                    final_props = ControlInterface.cull_props_by_rules(all_props, rule_list)\n                    comp_info = ComponentImpInfo(statement.description, rule_list, final_props, status)\n                    self.add_comp_info(imp_req.control_id, context.comp_name, label, comp_info)\n\n    def generate_control_rule_info(self, part_id_map: Dict[str, Dict[str, str]], context: ControlContext) -> None:\n\"\"\"\n        Generate rule info for controls directly from the components.\n\n        Args:\n            part_id_map: Mapping of label to part in the control\n            context: Control context for the current operation\n\n        Returns:\n            Returns nothing but places the rules_dict and rules_params_dict in the context for each component\n        \"\"\"\n        context.rules_dict = {}\n        context.rules_params_dict = {}\n        comps_uuids = []\n        for comp_def_name in context.comp_def_name_list:\n            context.comp_def, _ = ModelUtils.load_model_for_class(\n                context.trestle_root,\n                comp_def_name,\n                comp.ComponentDefinition\n            )\n            component_uuids = [comp.uuid for comp in context.comp_def.components]\n            comps_uuids.extend(component_uuids)\n            for component in as_list(context.comp_def.components):\n                context.component = component\n                context.comp_name = component.title\n                # get top level rule info applying to all controls from the component props\n                comp_rules_dict, comp_rules_params_dict, comp_rules_props = ControlInterface.get_rules_and_params_dict_from_item(component)  # noqa E501\n                context.rules_dict[context.comp_name] = comp_rules_dict\n                deep_update(context.rules_params_dict, [context.comp_name], comp_rules_params_dict)\n                for control_imp in as_list(component.control_implementations):\n                    context.control_implementation = control_imp\n                    self._add_control_imp_comp_info(context, part_id_map, comp_rules_props)\n                # add the rule_id to the param_dict\n                for param_comp_name, rule_param_dict in context.rules_params_dict.items():\n                    for rule_tag, params_list in rule_param_dict.items():\n                        for param in params_list:\n                            rule_dict = deep_get(context.rules_dict, [param_comp_name, rule_tag], {})\n                            param[const.HEADER_RULE_ID] = rule_dict.get(const.NAME, 'unknown_rule')\n        # determine if there are duplicated uuids and throw an exception\n        dup_comp_uuids = set({comp_uuid for comp_uuid in comps_uuids if comps_uuids.count(comp_uuid) > 1})\n        if len(dup_comp_uuids) > 0:\n            # throw an exception if there are repeated component uuids\n            for comp_uuid in dup_comp_uuids:\n                logger.error(f'Component uuid { comp_uuid } is duplicated')\n            raise TrestleError('Component uuids cannot be duplicated between different component definitions')\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.ControlHandle","title":" ControlHandle dataclass","text":"

                                                                            Convenience class for handling controls as members of a group.

                                                                            group_id: id of parent group or '' if not in a group group_title: title of the group group_class: class of the group path: path of parent groups leading to this control - without the final control_id, or [''] if in cat list important to remember that controls may not be in a group and are directly attached to cat control: the control itself

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            @dataclass\nclass ControlHandle:\n\"\"\"Convenience class for handling controls as members of a group.\n\n    group_id: id of parent group or '' if not in a group\n    group_title: title of the group\n    group_class: class of the group\n    path: path of parent groups leading to this control - without the final control_id, or [''] if in cat list\n    important to remember that controls may not be in a group and are directly attached to cat\n    control: the control itself\n    \"\"\"\n\n    group_id: str\n    group_title: Optional[str]\n    group_class: Optional[str]\n    group_path: List[str]\n    control_path: List[str]\n    control: cat.Control\n
                                                                            control: Control dataclass-field \u00a4 control_path: List[str] dataclass-field \u00a4 group_class: Optional[str] dataclass-field \u00a4 group_id: str dataclass-field \u00a4 group_path: List[str] dataclass-field \u00a4 group_title: Optional[str] dataclass-field \u00a4 __eq__(self, other) special \u00a4 __init__(self, group_id, group_title, group_class, group_path, control_path, control) special \u00a4 __repr__(self) special \u00a4"},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.__init__","title":"__init__(self, catalog=None) special","text":"

                                                                            Initialize the interface with the catalog.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def __init__(self, catalog: Optional[cat.Catalog] = None) -> None:\n\"\"\"Initialize the interface with the catalog.\"\"\"\n    self._catalog = catalog\n    self._param_control_map: Dict[str, str] = {}\n    self._generate_group_index: int = 0\n    self._control_dict = self._create_control_dict() if catalog else None\n    self.loose_param_dict: Dict[str, common.Parameter] = {param.id: param\n                                                          for param in as_list(catalog.params)} if catalog else {}\n    # map control id to CompDict\n    self._control_comp_dicts: Dict[str, CompDict] = {}\n    # map control id to dict containing set parameters by component\n    self._control_comp_set_params: Dict[str, Dict[str, comp.SetParameter]] = {}\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.add_comp_info","title":"add_comp_info(self, control_id, comp_name, label, comp_info)","text":"

                                                                            Add comp_info for a control.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def add_comp_info(self, control_id: str, comp_name: str, label: str, comp_info: ComponentImpInfo) -> None:\n\"\"\"Add comp_info for a control.\"\"\"\n    deep_set(self._control_comp_dicts, [control_id, comp_name, label], comp_info)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.add_comp_set_param","title":"add_comp_set_param(self, control_id, comp_name, set_param)","text":"

                                                                            Add component setparam for control with overwrite.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def add_comp_set_param(self, control_id: str, comp_name: str, set_param: comp.SetParameter) -> None:\n\"\"\"Add component setparam for control with overwrite.\"\"\"\n    deep_append(self._control_comp_set_params, [control_id, comp_name], set_param)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.clear_comp_dicts","title":"clear_comp_dicts(self)","text":"

                                                                            Clear the control component dicts.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def clear_comp_dicts(self) -> None:\n\"\"\"Clear the control component dicts.\"\"\"\n    self._control_comp_dicts = {}\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.clear_set_params","title":"clear_set_params(self)","text":"

                                                                            Clear the control set params.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def clear_set_params(self) -> None:\n\"\"\"Clear the control set params.\"\"\"\n    self._control_comp_set_params = {}\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.delete_control","title":"delete_control(self, control_id)","text":"

                                                                            Delete the control from the control_dict based on id.

                                                                            Delete all its dependent children also.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def delete_control(self, control_id: str) -> None:\n\"\"\"\n    Delete the control from the control_dict based on id.\n\n    Delete all its dependent children also.\n    \"\"\"\n    control = self.get_control(control_id)\n    if control:\n        for sub_control_id in self.get_dependent_control_ids(control.id):\n            self._control_dict.pop(sub_control_id, None)\n        self._control_dict.pop(control_id, None)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.delete_withdrawn_controls","title":"delete_withdrawn_controls(self)","text":"

                                                                            Delete all withdrawn controls from the catalog.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def delete_withdrawn_controls(self) -> None:\n\"\"\"Delete all withdrawn controls from the catalog.\"\"\"\n    delete_list = []\n    for control in self.get_all_controls_from_dict():\n        if ControlInterface.is_withdrawn(control):\n            delete_list.append(control.id)\n    for id_ in delete_list:\n        self.delete_control(id_)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.find_part_with_condition","title":"find_part_with_condition(self, part, condition)","text":"

                                                                            Traverse part and find subpart that satisfies given condition.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def find_part_with_condition(self, part: common.Part, condition: Callable) -> Optional[common.Part]:\n\"\"\"Traverse part and find subpart that satisfies given condition.\"\"\"\n    if condition(part):\n        # Part that satisfies the condition is found.\n        return part\n    else:\n        if part.parts:\n            for subpart in part.parts:\n                found_part = self.find_part_with_condition(subpart, condition)\n                if found_part:\n                    return found_part\n\n    return None\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.find_string_in_control","title":"find_string_in_control(self, control, seek_str)","text":"

                                                                            Find all instances of this string in prose of control.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def find_string_in_control(self, control: cat.Control, seek_str: str) -> List[Tuple[str, str]]:\n\"\"\"Find all instances of this string in prose of control.\"\"\"\n    hits: List[Tuple[str, str]] = []\n    if control.parts:\n        for part in control.parts:\n            hits.extend(self._find_string_in_part(control.id, part, seek_str))\n    return hits\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.generate_control_rule_info","title":"generate_control_rule_info(self, part_id_map, context)","text":"

                                                                            Generate rule info for controls directly from the components.

                                                                            Parameters:

                                                                            Name Type Description Default part_id_map Dict[str, Dict[str, str]]

                                                                            Mapping of label to part in the control

                                                                            required context ControlContext

                                                                            Control context for the current operation

                                                                            required

                                                                            Returns:

                                                                            Type Description None

                                                                            Returns nothing but places the rules_dict and rules_params_dict in the context for each component

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def generate_control_rule_info(self, part_id_map: Dict[str, Dict[str, str]], context: ControlContext) -> None:\n\"\"\"\n    Generate rule info for controls directly from the components.\n\n    Args:\n        part_id_map: Mapping of label to part in the control\n        context: Control context for the current operation\n\n    Returns:\n        Returns nothing but places the rules_dict and rules_params_dict in the context for each component\n    \"\"\"\n    context.rules_dict = {}\n    context.rules_params_dict = {}\n    comps_uuids = []\n    for comp_def_name in context.comp_def_name_list:\n        context.comp_def, _ = ModelUtils.load_model_for_class(\n            context.trestle_root,\n            comp_def_name,\n            comp.ComponentDefinition\n        )\n        component_uuids = [comp.uuid for comp in context.comp_def.components]\n        comps_uuids.extend(component_uuids)\n        for component in as_list(context.comp_def.components):\n            context.component = component\n            context.comp_name = component.title\n            # get top level rule info applying to all controls from the component props\n            comp_rules_dict, comp_rules_params_dict, comp_rules_props = ControlInterface.get_rules_and_params_dict_from_item(component)  # noqa E501\n            context.rules_dict[context.comp_name] = comp_rules_dict\n            deep_update(context.rules_params_dict, [context.comp_name], comp_rules_params_dict)\n            for control_imp in as_list(component.control_implementations):\n                context.control_implementation = control_imp\n                self._add_control_imp_comp_info(context, part_id_map, comp_rules_props)\n            # add the rule_id to the param_dict\n            for param_comp_name, rule_param_dict in context.rules_params_dict.items():\n                for rule_tag, params_list in rule_param_dict.items():\n                    for param in params_list:\n                        rule_dict = deep_get(context.rules_dict, [param_comp_name, rule_tag], {})\n                        param[const.HEADER_RULE_ID] = rule_dict.get(const.NAME, 'unknown_rule')\n    # determine if there are duplicated uuids and throw an exception\n    dup_comp_uuids = set({comp_uuid for comp_uuid in comps_uuids if comps_uuids.count(comp_uuid) > 1})\n    if len(dup_comp_uuids) > 0:\n        # throw an exception if there are repeated component uuids\n        for comp_uuid in dup_comp_uuids:\n            logger.error(f'Component uuid { comp_uuid } is duplicated')\n        raise TrestleError('Component uuids cannot be duplicated between different component definitions')\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_all_controls_from_catalog","title":"get_all_controls_from_catalog(self, recurse)","text":"

                                                                            Yield all controls from the actual catalog by group including optional sub controls.

                                                                            Parameters:

                                                                            Name Type Description Default recurse bool

                                                                            Whether to recurse within controls, but groups are always recursed

                                                                            required

                                                                            Returns:

                                                                            Type Description Iterator[trestle.oscal.catalog.Control]

                                                                            iterator of the controls in the catalog

                                                                            Notes

                                                                            This follows the actual structure of the catalog and groups

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_all_controls_from_catalog(self, recurse: bool) -> Iterator[cat.Control]:\n\"\"\"\n    Yield all controls from the actual catalog by group including optional sub controls.\n\n    Args:\n        recurse: Whether to recurse within controls, but groups are always recursed\n\n    Returns:\n        iterator of the controls in the catalog\n\n    Notes:\n        This follows the actual structure of the catalog and groups\n    \"\"\"\n    if self._catalog.groups:\n        for group in self._catalog.groups:\n            controls = self._get_all_controls_in_group(group, recurse)\n            for control in controls:\n                yield control\n    if self._catalog.controls:\n        cat_controls = self._get_all_controls_in_list(self._catalog.controls, recurse)\n        for control in cat_controls:\n            yield control\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_all_controls_from_dict","title":"get_all_controls_from_dict(self)","text":"

                                                                            Yield individual controls from the dict.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_all_controls_from_dict(self) -> List[cat.Control]:\n\"\"\"Yield individual controls from the dict.\"\"\"\n    return [handle.control for handle in self._control_dict.values()]\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_all_groups_from_catalog","title":"get_all_groups_from_catalog(self)","text":"

                                                                            Retrieve all groups in the catalog sorted by group_id.

                                                                            This ignores controls that are direct children of the catalog.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_all_groups_from_catalog(self) -> List[cat.Group]:\n\"\"\"\n    Retrieve all groups in the catalog sorted by group_id.\n\n    This ignores controls that are direct children of the catalog.\n    \"\"\"\n    groups: List[cat.Group] = []\n    if self._catalog.groups:\n        for my_group in self._catalog.groups:\n            for res in CatalogInterface._get_groups_from_group(my_group):\n                groups.append(res)\n    return sorted(groups, key=lambda group: group.id)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_catalog","title":"get_catalog(self, update=True)","text":"

                                                                            Safe method to get catalog after forced update from catalog dict.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_catalog(self, update=True) -> cat.Catalog:\n\"\"\"Safe method to get catalog after forced update from catalog dict.\"\"\"\n    if update:\n        self.update_catalog_controls()\n    return self._catalog\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_catalog_title","title":"get_catalog_title(self)","text":"

                                                                            Get the title of the catalog.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_catalog_title(self) -> str:\n\"\"\"Get the title of the catalog.\"\"\"\n    return self._catalog.metadata.title\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_comp_info","title":"get_comp_info(self, control_id)","text":"

                                                                            Get comp_dict for this control.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_comp_info(self, control_id: str) -> CompDict:\n\"\"\"Get comp_dict for this control.\"\"\"\n    return self._control_comp_dicts.get(control_id, {})\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control","title":"get_control(self, control_id)","text":"

                                                                            Get control from the control dict with this id.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control(self, control_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from the control dict with this id.\"\"\"\n    return None if control_id not in self._control_dict else self._control_dict[control_id].control\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_by_param_id","title":"get_control_by_param_id(self, param_id)","text":"

                                                                            Get control from catalog that has this param id using the dict.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control_by_param_id(self, param_id: str) -> Optional[cat.Control]:\n\"\"\"Get control from catalog that has this param id using the dict.\"\"\"\n    if param_id in self._param_control_map:\n        return self.get_control(self._param_control_map[param_id])\n    return None\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_comp_set_params","title":"get_control_comp_set_params(self, control_id)","text":"

                                                                            Get dict of setparams list per component.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control_comp_set_params(self, control_id: str) -> Dict[str, List[comp.SetParameter]]:\n\"\"\"Get dict of setparams list per component.\"\"\"\n    return self._control_comp_set_params.get(control_id, {})\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_file_path","title":"get_control_file_path(self, md_root, control_id)","text":"

                                                                            Get the path to the control from the given root.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control_file_path(self, md_root: pathlib.Path, control_id: str) -> Optional[pathlib.Path]:\n\"\"\"Get the path to the control from the given root.\"\"\"\n    if control_id not in self._control_dict:\n        return None\n    path = md_root\n    for item in self.get_control_path(control_id):\n        path = path / item\n    return path / f'{control_id}.md'\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_id_and_status","title":"get_control_id_and_status(self, control_name)","text":"

                                                                            Get the control id and status using the control name.

                                                                            Returns empty string if status not found.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control_id_and_status(self, control_name: str) -> Tuple[str, str]:\n\"\"\"\n    Get the control id and status using the control name.\n\n    Returns empty string if status not found.\n    \"\"\"\n    for control in self.get_all_controls_from_dict():\n        if ControlInterface.get_label(control).strip().lower() == control_name.strip().lower():\n            status = ControlInterface.get_prop(control, 'status')\n            return control.id, status\n    return '', ''\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_ids","title":"get_control_ids(self)","text":"

                                                                            Get all control ids from the control dict.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control_ids(self) -> List[str]:\n\"\"\"Get all control ids from the control dict.\"\"\"\n    return self._control_dict.keys()\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_ids_from_catalog","title":"get_control_ids_from_catalog(catalog) staticmethod","text":"

                                                                            Get all control ids from a catalog.

                                                                            This is intended to provide a quick list of all controls in a catalog without the expense of building the control dict. So, if repeated queries are made into a catalog, it is worth instantiating a CatalogInterface and associated control dict. Otherwise just use this to get a list of all controls.

                                                                            This function is needed within the CatalogInterface in order to determine if new controls have been added to the dict and need to be inserted in the actual catalog during update.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            @staticmethod\ndef get_control_ids_from_catalog(catalog: cat.Catalog) -> List[str]:\n\"\"\"\n    Get all control ids from a catalog.\n\n    This is intended to provide a quick list of all controls in a catalog without the expense of building the\n    control dict.  So, if repeated queries are made into a catalog, it is worth instantiating a CatalogInterface\n    and associated control dict.  Otherwise just use this to get a list of all controls.\n\n    This function is needed within the CatalogInterface in order to determine if new controls have been added\n    to the dict and need to be inserted in the actual catalog during update.\n    \"\"\"\n    controls = CatalogInterface._get_all_controls_in_list(as_list(catalog.controls), True)\n    id_list = [control.id for control in controls]\n    for group in as_list(catalog.groups):\n        controls = CatalogInterface._get_all_controls_in_group(group, True)\n        id_list.extend([control.id for control in as_list(controls)])\n    return id_list\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_part_prose","title":"get_control_part_prose(self, control_id, part_name)","text":"

                                                                            Get the prose for a named part in the control.

                                                                            Parameters:

                                                                            Name Type Description Default control_id str

                                                                            id of the control

                                                                            required part_name str

                                                                            name of the part

                                                                            required

                                                                            Returns:

                                                                            Type Description str

                                                                            Single string concatenating prose from all parts and sub-parts in control with that name.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control_part_prose(self, control_id: str, part_name: str) -> str:\n\"\"\"\n    Get the prose for a named part in the control.\n\n    Args:\n        control_id: id of the control\n        part_name: name of the part\n\n    Returns:\n        Single string concatenating prose from all parts and sub-parts in control with that name.\n    \"\"\"\n    control = self.get_control(control_id)\n    return ControlInterface.get_part_prose(control, part_name)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_control_path","title":"get_control_path(self, control_id)","text":"

                                                                            Return the path into the markdown directory for this control based only on the groups.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path into the markdown directory for this control based only on the groups.\"\"\"\n    return self._control_dict[control_id].group_path\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_count_of_controls_in_catalog","title":"get_count_of_controls_in_catalog(self, recurse)","text":"

                                                                            Get count of controls from the actual catalog including optional sub controls.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_count_of_controls_in_catalog(self, recurse: bool) -> int:\n\"\"\"Get count of controls from the actual catalog including optional sub controls.\"\"\"\n    return len(list(self.get_all_controls_from_catalog(recurse)))\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_count_of_controls_in_dict","title":"get_count_of_controls_in_dict(self)","text":"

                                                                            Find number of controls in the dict.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_count_of_controls_in_dict(self) -> int:\n\"\"\"Find number of controls in the dict.\"\"\"\n    return len(self._control_dict.keys())\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_dependent_control_ids","title":"get_dependent_control_ids(self, control_id)","text":"

                                                                            Find all child ids of this control from the dict with recursion.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_dependent_control_ids(self, control_id: str) -> List[str]:\n\"\"\"Find all child ids of this control from the dict with recursion.\"\"\"\n    children: List[str] = []\n    control = self.get_control(control_id)\n    if control:\n        new_controls = self._get_all_controls_in_list(as_list(control.controls), True)\n        children.extend([con.id for con in new_controls])\n    return children\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_full_control_path","title":"get_full_control_path(self, control_id)","text":"

                                                                            Return the path to the control including groups and sub-controls.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_full_control_path(self, control_id: str) -> List[str]:\n\"\"\"Return the path to the control including groups and sub-controls.\"\"\"\n    return self._control_dict[control_id].control_path\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_group_ids","title":"get_group_ids(self)","text":"

                                                                            Get all the group id's as a list of sorted strings.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_group_ids(self) -> List[str]:\n\"\"\"Get all the group id's as a list of sorted strings.\"\"\"\n    return sorted(filter(lambda id_: id_, list({control.group_id for control in self._control_dict.values()})))\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_group_info_by_control","title":"get_group_info_by_control(self, control_id)","text":"

                                                                            Get the group_id, title, class for this control from the dict.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_group_info_by_control(self, control_id: str) -> Tuple[str, str, str]:\n\"\"\"Get the group_id, title, class for this control from the dict.\"\"\"\n    return (\n        '' if self._control_dict is None else self._control_dict[control_id].group_id,\n        '' if self._control_dict is None else self._control_dict[control_id].group_title,\n        '' if self._control_dict is None else self._control_dict[control_id].group_class\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_sections","title":"get_sections(self)","text":"

                                                                            Get the available sections by a full index of all controls.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_sections(self) -> List[str]:\n\"\"\"Get the available sections by a full index of all controls.\"\"\"\n    return list(\n        {\n            part.name\n            for control_handle in self._control_dict.values()\n            for part in as_list(control_handle.control.parts)\n            if part.name != const.STATEMENT\n        }\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_sorted_controls_in_group","title":"get_sorted_controls_in_group(self, group_id)","text":"

                                                                            Get the list of controls in a group sorted by the control sort-id.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_sorted_controls_in_group(self, group_id: str) -> List[cat.Control]:\n\"\"\"Get the list of controls in a group sorted by the control sort-id.\"\"\"\n    controls: List[cat.Control] = []\n    for control in self.get_all_controls_from_dict():\n        grp_id, _, _ = self.get_group_info_by_control(control.id)\n        if grp_id == group_id:\n            controls.append(control)\n    return sorted(controls, key=lambda control: ControlInterface.get_sort_id(control))\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_statement_label_if_exists","title":"get_statement_label_if_exists(self, control_id, statement_id)","text":"

                                                                            Get statement label if available.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_statement_label_if_exists(self, control_id: str,\n                                  statement_id: str) -> Tuple[Optional[str], Optional[common.Part]]:\n\"\"\"Get statement label if available.\"\"\"\n\n    def does_part_exists(part: common.Part) -> bool:\n        does_match = False\n        if part.name and part.name in {const.STATEMENT, const.ITEM} and part.id == statement_id:\n            does_match = True\n        return does_match\n\n    control = self.get_control(control_id)\n    if not control:\n        return '', None\n    label = None\n    found_part = None\n    if control.parts:\n        for part in as_list(control.parts):\n            # Performance OSCAL assumption, ids are nested so recurse only if prefix\n            if part.id and statement_id.startswith(part.id):\n                part = self.find_part_with_condition(part, does_part_exists)\n                if part:\n                    label = ControlInterface.get_label(part)\n                    found_part = part\n                    break\n\n    return label, found_part\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_statement_part_id_map","title":"get_statement_part_id_map(self, label_as_key)","text":"

                                                                            Create mapping of label to part_id for top level parts in statement of all controls.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_statement_part_id_map(self, label_as_key: bool) -> Dict[str, Dict[str, str]]:\n\"\"\"Create mapping of label to part_id for top level parts in statement of all controls.\"\"\"\n    id_map = {}\n    for control in self.get_all_controls_from_catalog(True):\n        statement_part = get_item_from_list(control.parts, const.STATEMENT, lambda p: p.name)\n        if not statement_part:\n            continue\n        id_dict: Dict[str, str] = {}\n        for sub_part in as_list(statement_part.parts):\n            label = ControlInterface.get_label(sub_part)\n            # skip add to map for empty label\n            if not label:\n                continue\n            if label_as_key:\n                id_dict[label] = sub_part.id\n            else:\n                id_dict[sub_part.id] = label\n        if id_dict:\n            id_map[control.id] = id_dict\n    return id_map\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.get_statement_parts","title":"get_statement_parts(self, control_id)","text":"

                                                                            Get list of statement parts as dicts with indentation, label and prose.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def get_statement_parts(self, control_id: str) -> List[Dict[str, str]]:\n\"\"\"Get list of statement parts as dicts with indentation, label and prose.\"\"\"\n    items = []\n    control = self.get_control(control_id)\n\n    # control may have no statement or parts\n    # but if statement present it is first part\n    if control is None:\n        logger.warning(f'No control found for id {control_id}')\n    elif control.parts:\n        part = control.parts[0]\n        if part.name == 'statement':\n            items.extend(CatalogInterface._get_statement_sub_parts(part, 0))\n        else:\n            logger.warning(f'Control {control_id} has parts but first part name is {part.name} - not statement')\n    return items\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.replace_control","title":"replace_control(self, control)","text":"

                                                                            Replace the control in the control_dict.

                                                                            This only replaces the parent control and not its children.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def replace_control(self, control: cat.Control) -> None:\n\"\"\"\n    Replace the control in the control_dict.\n\n    This only replaces the parent control and not its children.\n    \"\"\"\n    self._control_dict[control.id].control = control\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_interface/#trestle.core.catalog.catalog_interface.CatalogInterface.update_catalog_controls","title":"update_catalog_controls(self)","text":"

                                                                            Update the actual catalog by pulling fresh controls from the dict.

                                                                            During assembly, controls may be added, but not children of controls. New groups may not be added. A control containing controls cannot be added. Controls containing controls are only available if the parent catalog was loaded from json.

                                                                            Source code in trestle/core/catalog/catalog_interface.py
                                                                            def update_catalog_controls(self) -> None:\n\"\"\"\n    Update the actual catalog by pulling fresh controls from the dict.\n\n    During assembly, controls may be added, but not children of controls.\n    New groups may not be added.\n    A control containing controls cannot be added.  Controls containing controls are only available if\n    the parent catalog was loaded from json.\n    \"\"\"\n    # first go through the catalog and pull existing controls from the dict\n    for group in as_list(self._catalog.groups):\n        self._update_all_controls_in_group(group)\n\n    new_list = []\n    for control in as_list(self._catalog.controls):\n        new_control = self.get_control(control.id)\n        new_control.controls = self._update_all_controls_in_list(as_list(control.controls))\n        new_control.controls = none_if_empty(new_control.controls)\n        new_list.append(new_control)\n    self._catalog.controls = none_if_empty(new_list)\n\n    # now add any new controls that are discovered in the dict\n    ids_in_catalog = CatalogInterface.get_control_ids_from_catalog(self._catalog)\n    for control_handle in self._control_dict.values():\n        if control_handle.control.id not in ids_in_catalog:\n            self._insert_control_in_catalog(control_handle)\n\n    self._catalog.params = none_if_empty(list(self.loose_param_dict.values()))\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_merger/","title":"catalog_merger","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger","title":"trestle.core.catalog.catalog_merger","text":"

                                                                            Provide interface to merge one catalog to another.

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger","title":" CatalogMerger ","text":"

                                                                            Catalog merger.

                                                                            Catalog merger handles all operations related to merging contents of one catalog to another.

                                                                            Source code in trestle/core/catalog/catalog_merger.py
                                                                            class CatalogMerger():\n\"\"\"\n    Catalog merger.\n\n    Catalog merger handles all operations related to\n    merging contents of one catalog to another.\n    \"\"\"\n\n    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog merger.\"\"\"\n        self._catalog_interface = catalog_interface\n\n    @staticmethod\n    def merge_controls(dest: cat.Control, src: cat.Control, replace_params: bool) -> None:\n\"\"\"\n        Merge the src control into dest.\n\n        Args:\n            dest: destination control into which content will be added\n            src: source control with new content\n            replace_params: replace the control params with the new ones\n        \"\"\"\n        ControlInterface.merge_parts(dest, src)\n        if replace_params:\n            dest.params = src.params\n\n    def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"\n        Merge the provided new catalog controls into the original catalog in this catalog interface.\n\n        Args:\n            catalog: catalog containing controls that are merged into the current catalog of the interface\n            replace_params: replace all params in the control with the new ones\n\n        Notes:\n            This is mainly to support the reading of a catalog from markdown.  It allows retention of content such as\n            metadata and backmatter, along with labels and other parameter attributes that aren't in markdown.\n            The list of controls and group structure is specified by the markdown structure - but this doesn't allow\n            controls to contain controls.  Group lists are specified per directory.\n\n            Reading the markdown tells you groups and controls in them - and groups in groups.\n            Controls cannot change groups.  If the control was in the original json, its parts are replaced,\n            including its parameters.  Only values may be specified.  If no value specified, the value is unset in json.\n        \"\"\"\n        cat_interface = CatalogInterface(catalog)\n        for src in cat_interface.get_all_controls_from_dict():\n            group_id, _, _ = cat_interface.get_group_info_by_control(src.id)\n            dest = self._catalog_interface.get_control(src.id)\n            if dest:\n                dest_group, _, _ = self._catalog_interface.get_group_info_by_control(dest.id)\n                if dest_group != group_id:\n                    raise TrestleError(f'Markdown for control {src.id} has different group id.')\n                CatalogMerger.merge_controls(dest, src, replace_params)\n                self._catalog_interface.replace_control(dest)\n            else:\n                # this is a new control that isn't already in the merge destination\n                # need to add the control knowing its group must already exist\n                # get group info from an arbitrary control already present in group\n                _, control_handle = self._catalog_interface._find_control_in_group(group_id)\n                new_control_handle = copy.deepcopy(control_handle)\n                new_control_handle.control = src\n                # add the control and its handle to the param_dict\n                self._catalog_interface._control_dict[src.id] = new_control_handle  # type: ignore\n\n        # now need to cull any controls that are not in the src catalog\n        if cat_interface._control_dict is None:\n            handled_ids = None\n        else:\n            handled_ids = set(cat_interface._control_dict.keys())\n        orig_ids = set(self._catalog_interface._control_dict.keys())\n        extra_ids = orig_ids.difference(handled_ids)\n        for extra_id in sorted(extra_ids):\n            self._catalog_interface._control_dict.pop(extra_id)\n\n        self._catalog_interface.update_catalog_controls()\n\n    def _merge_header_and_comp_dict(\n        self, control: cat.Control, control_file_path: pathlib.Path, context: ControlContext\n    ) -> None:\n\"\"\"\n        Merge the header and the comp_dict.\n\n        Notes:\n            now have all rules in context.rules_dict and all rules_params in context.rules_params_dict\n            all set-params per component for each control are in the cat interface\n            all comp-infos by control and part are in the cat interface\n\n            can now write out catalog and pull from the markdown:\n            header for param values to set during assem\n            prose and status for This System\n            status for all parts that still have rules\n        \"\"\"\n        memory_header, memory_comp_dict = self._catalog_interface._get_control_memory_info(control.id, context)\n        ControlInterface.merge_dicts_deep(memory_header, context.merged_header, True)\n        md_header, md_comp_dict = CatalogReader._read_comp_info_from_md(control_file_path, context)\n        # md content replaces memory content but unless memory has no rules for it and the content is removed\n        # but This System doesn't require rules, so its content is always kept\n\n        # go through the just-read md_comp_dict and update the memory dict with contents in md\n        if const.SSP_MAIN_COMP_NAME in md_comp_dict:\n            memory_comp_dict[const.SSP_MAIN_COMP_NAME] = md_comp_dict[const.SSP_MAIN_COMP_NAME]\n        for comp_name, md_label_dict in md_comp_dict.items():\n            memory_label_dict = memory_comp_dict.get(comp_name, None)\n            if comp_name != const.SSP_MAIN_COMP_NAME:\n                if not memory_label_dict:\n                    continue\n                for label, comp_info in md_label_dict.items():\n                    if label in memory_label_dict:\n                        memory_label_dict[label] = comp_info\n\n        memory_rules_param_vals = memory_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {})\n        md_rules_param_vals = md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {})\n        for comp_name, val_list in md_rules_param_vals.items():\n            val_dict = {val['name']: val for val in val_list}\n            if comp_name not in memory_rules_param_vals:\n                memory_rules_param_vals[comp_name] = val_list\n            else:\n                # merge the lists with priority to md\n                new_list = []\n                mem_list = memory_rules_param_vals[comp_name]\n                mem_names = [mem['name'] for mem in mem_list]\n                for val in mem_list:\n                    new_list.append(val_dict.get(val['name'], val))\n                for key, val in val_dict.items():\n                    if key not in mem_names:\n                        new_list.append(val)\n                memory_rules_param_vals[comp_name] = new_list\n\n        set_or_pop(memory_header, const.COMP_DEF_RULES_PARAM_VALS_TAG, memory_rules_param_vals)\n        context.merged_header = memory_header\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger.__init__","title":"__init__(self, catalog_interface) special","text":"

                                                                            Initialize catalog merger.

                                                                            Source code in trestle/core/catalog/catalog_merger.py
                                                                            def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog merger.\"\"\"\n    self._catalog_interface = catalog_interface\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger.merge_catalog","title":"merge_catalog(self, catalog, replace_params)","text":"

                                                                            Merge the provided new catalog controls into the original catalog in this catalog interface.

                                                                            Parameters:

                                                                            Name Type Description Default catalog Catalog

                                                                            catalog containing controls that are merged into the current catalog of the interface

                                                                            required replace_params bool

                                                                            replace all params in the control with the new ones

                                                                            required

                                                                            Notes

                                                                            This is mainly to support the reading of a catalog from markdown. It allows retention of content such as metadata and backmatter, along with labels and other parameter attributes that aren't in markdown. The list of controls and group structure is specified by the markdown structure - but this doesn't allow controls to contain controls. Group lists are specified per directory.

                                                                            Reading the markdown tells you groups and controls in them - and groups in groups. Controls cannot change groups. If the control was in the original json, its parts are replaced, including its parameters. Only values may be specified. If no value specified, the value is unset in json.

                                                                            Source code in trestle/core/catalog/catalog_merger.py
                                                                            def merge_catalog(self, catalog: cat.Catalog, replace_params: bool) -> None:\n\"\"\"\n    Merge the provided new catalog controls into the original catalog in this catalog interface.\n\n    Args:\n        catalog: catalog containing controls that are merged into the current catalog of the interface\n        replace_params: replace all params in the control with the new ones\n\n    Notes:\n        This is mainly to support the reading of a catalog from markdown.  It allows retention of content such as\n        metadata and backmatter, along with labels and other parameter attributes that aren't in markdown.\n        The list of controls and group structure is specified by the markdown structure - but this doesn't allow\n        controls to contain controls.  Group lists are specified per directory.\n\n        Reading the markdown tells you groups and controls in them - and groups in groups.\n        Controls cannot change groups.  If the control was in the original json, its parts are replaced,\n        including its parameters.  Only values may be specified.  If no value specified, the value is unset in json.\n    \"\"\"\n    cat_interface = CatalogInterface(catalog)\n    for src in cat_interface.get_all_controls_from_dict():\n        group_id, _, _ = cat_interface.get_group_info_by_control(src.id)\n        dest = self._catalog_interface.get_control(src.id)\n        if dest:\n            dest_group, _, _ = self._catalog_interface.get_group_info_by_control(dest.id)\n            if dest_group != group_id:\n                raise TrestleError(f'Markdown for control {src.id} has different group id.')\n            CatalogMerger.merge_controls(dest, src, replace_params)\n            self._catalog_interface.replace_control(dest)\n        else:\n            # this is a new control that isn't already in the merge destination\n            # need to add the control knowing its group must already exist\n            # get group info from an arbitrary control already present in group\n            _, control_handle = self._catalog_interface._find_control_in_group(group_id)\n            new_control_handle = copy.deepcopy(control_handle)\n            new_control_handle.control = src\n            # add the control and its handle to the param_dict\n            self._catalog_interface._control_dict[src.id] = new_control_handle  # type: ignore\n\n    # now need to cull any controls that are not in the src catalog\n    if cat_interface._control_dict is None:\n        handled_ids = None\n    else:\n        handled_ids = set(cat_interface._control_dict.keys())\n    orig_ids = set(self._catalog_interface._control_dict.keys())\n    extra_ids = orig_ids.difference(handled_ids)\n    for extra_id in sorted(extra_ids):\n        self._catalog_interface._control_dict.pop(extra_id)\n\n    self._catalog_interface.update_catalog_controls()\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_merger/#trestle.core.catalog.catalog_merger.CatalogMerger.merge_controls","title":"merge_controls(dest, src, replace_params) staticmethod","text":"

                                                                            Merge the src control into dest.

                                                                            Parameters:

                                                                            Name Type Description Default dest Control

                                                                            destination control into which content will be added

                                                                            required src Control

                                                                            source control with new content

                                                                            required replace_params bool

                                                                            replace the control params with the new ones

                                                                            required Source code in trestle/core/catalog/catalog_merger.py
                                                                            @staticmethod\ndef merge_controls(dest: cat.Control, src: cat.Control, replace_params: bool) -> None:\n\"\"\"\n    Merge the src control into dest.\n\n    Args:\n        dest: destination control into which content will be added\n        src: source control with new content\n        replace_params: replace the control params with the new ones\n    \"\"\"\n    ControlInterface.merge_parts(dest, src)\n    if replace_params:\n        dest.params = src.params\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/","title":"catalog_reader","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader","title":"trestle.core.catalog.catalog_reader","text":"

                                                                            Provide interface to read catalog from markdown back to OSCAL.

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader","title":" CatalogReader ","text":"

                                                                            Catalog reader.

                                                                            Catalog reader handles all operations related to reading catalog from markdown.

                                                                            Source code in trestle/core/catalog/catalog_reader.py
                                                                            class CatalogReader():\n\"\"\"\n    Catalog reader.\n\n    Catalog reader handles all operations related to\n    reading catalog from markdown.\n    \"\"\"\n\n    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog reader.\"\"\"\n        self._catalog_interface = catalog_interface\n\n    def read_additional_content(\n        self,\n        md_path: pathlib.Path,\n        required_sections_list: List[str],\n        label_map: Dict[str, Dict[str, str]],\n        sections_dict: Dict[str, str],\n        write_mode: bool\n    ) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read all markdown controls and return list of alters plus control param dict and param sort map.\"\"\"\n        alters_map: Dict[str, prof.Alter] = {}\n        final_param_dict: Dict[str, Any] = {}\n        param_sort_map: Dict[str, str] = {}\n        for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n            for control_file in group_path.glob('*.md'):\n                sort_id, control_alters, control_param_dict = ControlReader.read_editable_content(\n                    control_file,\n                    required_sections_list,\n                    label_map,\n                    sections_dict,\n                    write_mode\n                )\n                alters_map[sort_id] = control_alters\n                for param_id, param_dict in control_param_dict.items():\n                    # if profile_values are present, overwrite values with them\n                    if const.PROFILE_VALUES in param_dict:\n                        if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                            if not write_mode and const.REPLACE_ME_PLACEHOLDER in param_dict[const.PROFILE_VALUES]:\n                                param_dict[const.PROFILE_VALUES].remove(const.REPLACE_ME_PLACEHOLDER)\n                            if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                                param_dict[const.VALUES] = param_dict[const.PROFILE_VALUES]\n                        if not write_mode:\n                            param_dict.pop(const.PROFILE_VALUES)\n                    # verifies if at control profile edition the param value origin was modified\n                    # through the profile-param-value-origin tag\n                    if const.PROFILE_PARAM_VALUE_ORIGIN in param_dict:\n                        if param_dict[const.PROFILE_PARAM_VALUE_ORIGIN] != const.REPLACE_ME_PLACEHOLDER:\n                            param_dict[const.PARAM_VALUE_ORIGIN] = param_dict[const.PROFILE_PARAM_VALUE_ORIGIN]\n                            param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                        else:\n                            # removes replace me placeholder and profile-param-value-origin as it was not modified\n                            param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                            # validates param-value-origin is in dict to remove it\n                            # because a value wasn\u00b4t provided and it shouldn\u00b4t be inheriting value from parent\n                            if const.PARAM_VALUE_ORIGIN in param_dict:\n                                param_dict.pop(const.PARAM_VALUE_ORIGIN)\n                    final_param_dict[param_id] = param_dict\n                    param_sort_map[param_id] = sort_id\n        new_alters: List[prof.Alter] = []\n        # fill the alters according to the control sorting order\n        for key in sorted(alters_map.keys()):\n            new_alters.extend(alters_map[key])\n        return new_alters, final_param_dict, param_sort_map\n\n    def read_catalog_from_markdown(self, md_path: pathlib.Path, set_parameters_flag: bool) -> cat.Catalog:\n\"\"\"\n        Read the groups and catalog controls from the given directory.\n\n        This will overwrite the existing groups and controls in the catalog.\n        \"\"\"\n        id_map = CatalogInterface._get_group_ids_and_dirs(md_path)\n        groups: List[cat.Group] = []\n        # read each group dir\n        for group_id, group_dir in id_map.items():\n            control_list_raw = []\n            group_title = ''\n            # Need to get group title from at least one control in this directory\n            # All controls in dir should have same group title\n            # Set group title to the first one found and warn if different non-empty title appears\n            # Controls with empty group titles are tolerated but at least one title must be present or warning given\n            # The special group with no name that has the catalog as parent is just a list and has no title\n            for control_path in group_dir.glob('*.md'):\n                control, control_group_title = ControlReader.read_control(control_path, set_parameters_flag)\n                if control_group_title:\n                    if group_title:\n                        if control_group_title != group_title:\n                            logger.warning(\n                                f'Control {control.id} group title {control_group_title} differs from {group_title}'\n                            )\n                    else:\n                        group_title = control_group_title\n                control_list_raw.append(control)\n            control_list = sorted(control_list_raw, key=lambda control: ControlInterface.get_sort_id(control))\n            if group_id:\n                if not group_title:\n                    logger.warning(\n                        f'No group title found in controls for group {group_id}.  The title will be recovered if assembling into an existing catalog with the group title defined.'  # noqa E501\n                    )\n                new_group = cat.Group(id=group_id, title=group_title)\n                new_group.controls = none_if_empty(control_list)\n                groups.append(new_group)\n            else:\n                # if the list of controls has no group id it also has no title and is just the controls of the catalog\n                self._catalog_interface._catalog.controls = none_if_empty(control_list)\n        self._catalog_interface._catalog.groups = none_if_empty(groups)\n        self._catalog_interface._create_control_dict()\n        self._catalog_interface._catalog.params = none_if_empty(self._catalog_interface._catalog.params)\n        return self._catalog_interface._catalog\n\n    @staticmethod\n    def read_catalog_imp_reqs(md_path: pathlib.Path, context: ControlContext) -> List[comp.ImplementedRequirement]:\n\"\"\"Read the full set of control implemented requirements from markdown.\n\n        Args:\n            md_path: Path to the markdown control files, with directories for each group\n            context: Context for the operation\n\n        Returns:\n            List of implemented requirements gathered from each control\n\n        Notes:\n            As the controls are read into the catalog the needed components are added if not already available.\n            avail_comps provides the mapping of component name to the actual component.\n            This is only used during component assemble and only for updating one component\n        \"\"\"\n        imp_req_map: Dict[str, comp.ImplementedRequirement] = {}\n        for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n            for control_file in group_path.glob('*.md'):\n                sort_id, imp_req = ControlReader.read_implemented_requirement(control_file, context)\n                imp_req_map[sort_id] = imp_req\n        return [imp_req_map[key] for key in sorted(imp_req_map.keys())]\n\n    @staticmethod\n    def _get_imp_req_for_control(ssp: ossp.SystemSecurityPlan, control_id: str) -> ossp.ImplementedRequirement:\n        for imp_req in as_list(ssp.control_implementation.implemented_requirements):\n            if imp_req.control_id == control_id:\n                return imp_req\n        imp_req = gens.generate_sample_model(ossp.ImplementedRequirement)\n        imp_req.control_id = control_id\n        ssp.control_implementation.implemented_requirements = as_list(\n            ssp.control_implementation.implemented_requirements\n        )\n        ssp.control_implementation.implemented_requirements.append(imp_req)\n        return imp_req\n\n    @staticmethod\n    def _get_imp_req_for_statement(\n        ssp: ossp.SystemSecurityPlan, control_id: str, statement_id: str\n    ) -> ossp.ImplementedRequirement:\n        control_imp_req: Optional[ossp.ImplementedRequirement] = None\n        for imp_req in as_list(ssp.control_implementation.implemented_requirements):\n            if imp_req.control_id == control_id:\n                control_imp_req = imp_req\n                if statement_id in [stat.statement_id for stat in as_list(imp_req.statements)]:\n                    return imp_req\n        # we didn't find imp_req with statement so need to make statement and/or imp_req\n        if not control_imp_req:\n            control_imp_req = gens.generate_sample_model(ossp.ImplementedRequirement)\n            control_imp_req.control_id = control_id\n            control_imp_req.statements = None\n            ssp.control_implementation.implemented_requirements = as_list(\n                ssp.control_implementation.implemented_requirements\n            )\n            ssp.control_implementation.implemented_requirements.append(control_imp_req)\n        CatalogReader._add_statement_to_impl_requirement(control_imp_req, statement_id)\n        return control_imp_req\n\n    @staticmethod\n    def _add_statement_to_impl_requirement(impl_req: ossp.ImplementedRequirement, statement_id: str) -> ossp.Statement:\n\"\"\"Update the implemented requirement with a new statement.\"\"\"\n        statement = gens.generate_sample_model(ossp.Statement)\n        statement.statement_id = statement_id\n        statement.by_components = None\n        impl_req.statements = as_list(impl_req.statements)\n        impl_req.statements.append(statement)\n        return statement\n\n    @staticmethod\n    def _get_by_comp_from_imp_req(\n        imp_req: ossp.ImplementedRequirement, statement_id: str, comp_uuid: str\n    ) -> ossp.ByComponent:\n        if statement_id:\n            found_statement: Optional[ossp.Statement] = None\n            for statement in as_list(imp_req.statements):\n                if statement.statement_id == statement_id:\n                    found_statement = statement\n                    break\n\n            # If the statement doesn't exist, create it\n            if not found_statement:\n                found_statement = CatalogReader._add_statement_to_impl_requirement(imp_req, statement_id)\n            else:\n                for by_comp in as_list(found_statement.by_components):\n                    if by_comp.component_uuid == comp_uuid:\n                        return by_comp\n\n            # didnt find bycomp or new statement so need to make one\n            by_comp = gens.generate_sample_model(ossp.ByComponent)\n            by_comp.component_uuid = comp_uuid\n            by_comp.implementation_status = com.ImplementationStatus(state=const.STATUS_PLANNED)\n            found_statement.by_components = as_list(found_statement.by_components)\n            found_statement.by_components.append(by_comp)\n            return by_comp\n        else:\n            for by_comp in as_list(imp_req.by_components):\n                if by_comp.component_uuid == comp_uuid:\n                    return by_comp\n            by_comp = gens.generate_sample_model(ossp.ByComponent)\n            by_comp.component_uuid = comp_uuid\n            by_comp.implementation_status = com.ImplementationStatus(state=const.STATUS_PLANNED)\n            imp_req.by_components = as_list(imp_req.by_components)\n            imp_req.by_components.append(by_comp)\n            return by_comp\n\n    @staticmethod\n    def _read_comp_info_from_md(control_file_path: pathlib.Path,\n                                context: ControlContext) -> Tuple[Dict[str, Any], CompDict]:\n        md_header = {}\n        comp_dict = {}\n        if control_file_path.exists():\n            md_header, comp_dict = ControlReader.read_control_info_from_md(control_file_path, context)\n        return md_header, comp_dict\n\n    @staticmethod\n    def _update_ssp_with_comp_info(\n        ssp: ossp.SystemSecurityPlan,\n        control_id: str,\n        gen_comp: generic.GenericComponent,\n        comp_info_dict: Dict[str, ComponentImpInfo],\n        part_id_map_by_label: Dict[str, Dict[str, str]]\n    ) -> None:\n        # get imp req for control and find one with by_comp, creating if needed\n        imp_req = CatalogReader._get_imp_req_for_control(ssp, control_id)\n        # if control has no parts it will not have part id map and bycomps will go at control level\n        control_part_id_map = part_id_map_by_label.get(control_id, {})\n        for label, comp_info in comp_info_dict.items():\n            part_id = control_part_id_map.get(label, '')\n            by_comp = CatalogReader._get_by_comp_from_imp_req(imp_req, part_id, gen_comp.uuid)\n            by_comp.description = comp_info.prose\n            by_comp.implementation_status = comp_info.status\n\n    @staticmethod\n    def _insert_set_param_into_by_comps(\n        item: Union[ossp.ImplementedRequirement, ossp.ByComponent],\n        rule_id: str,\n        param_name: str,\n        param_values: List[str],\n        comp_uuid: str\n    ) -> None:\n        for by_comp in as_list(item.by_components):\n            if by_comp.component_uuid == comp_uuid:\n                for prop in as_list(by_comp.props):\n                    if prop.name == const.RULE_ID and prop.value == rule_id:\n                        found = False\n                        for sp in as_list(by_comp.set_parameters):\n                            if sp.param_id == param_name:\n                                sp.values = param_values\n                                found = True\n                                break\n                        if not found:\n                            sp = ossp.SetParameter(param_id=param_name, values=param_values)\n                            by_comp.set_parameters = as_list(by_comp.set_parameters)\n                            by_comp.set_parameters.append(sp)\n\n    @staticmethod\n    def _insert_param_dict_in_imp_req(\n        imp_req: ossp.ImplementedRequirement,\n        param_dict: Dict[str, str],\n        comp_name: str,\n        md_header: Dict[str, Dict[str, str]],\n        comp_uuid: str\n    ):\n\"\"\"Insert the param in the by_comps that are supported by the rule.\"\"\"\n        # given param name find rule_id in comp name header entry\n        # then find all statements with by_comp that have that rule id in props\n        rules_dict = md_header.get(const.RULES_PARAMS_TAG, {})\n        comp_rules_params = rules_dict.get(comp_name, [])\n        param_name = param_dict['name']\n        param_values = param_dict['values']\n        for comp_rule_param in comp_rules_params:\n            if comp_rule_param['name'] == param_name:\n                rule_id = comp_rule_param[const.HEADER_RULE_ID]\n                CatalogReader._insert_set_param_into_by_comps(imp_req, rule_id, param_name, param_values, comp_uuid)\n                for statement in as_list(imp_req.statements):\n                    CatalogReader._insert_set_param_into_by_comps(\n                        statement, rule_id, param_name, param_values, comp_uuid\n                    )\n\n    @staticmethod\n    def _add_set_params_to_item(param_dict: Dict[str, str], item: TypeWithSetParams, param_id: str) -> None:\n        value_list = param_dict[const.SSP_VALUES]\n        param_values = value_list\n        new_sp_list = []\n        for sp in as_list(item.set_parameters):\n            if sp.param_id != param_id:\n                new_sp_list.append(sp)\n        item.set_parameters = new_sp_list\n        item.set_parameters.append(ossp.SetParameter(param_id=param_id, values=param_values))\n\n    @staticmethod\n    def _add_props_to_imp_req(\n        control_id: str,\n        part_id_map_by_label: Dict[str, Dict[str, str]],\n        yaml_header: Dict[str, Any],\n        imp_req: ossp.ImplementedRequirement\n    ) -> None:\n\"\"\"Add the props from the yaml header to the imp_req.\"\"\"\n        control_part_id_map = part_id_map_by_label.get(control_id, {})\n        props, props_by_id = ControlReader.get_props_list(control_id, control_part_id_map, yaml_header)\n        # add the props at control level\n        if props:\n            imp_req.props = as_list(imp_req.props)\n            imp_req.props.extend(props)\n\n        # add the props at the part level\n        for label, part_id in control_part_id_map.items():\n            props = props_by_id.get(label, [])\n            if not props:\n                continue\n            for statement in as_list(imp_req.statements):\n                if statement.statement_id == part_id:\n                    statement.props = as_list(statement.props)\n                    statement.props.extend(props)\n\n    @staticmethod\n    def _update_ssp_with_md_header(\n        ssp: ossp.SystemSecurityPlan,\n        control_id: str,\n        comp_dict: Dict[str, generic.GenericComponent],\n        part_label_to_id_map: Dict[str, Dict[str, str]],\n        md_header: Dict[str, Dict[str, str]]\n    ) -> None:\n\"\"\"Update the ssp with info from the header of an ssp control markdown file.\"\"\"\n        # rules param vals go in bycomps of imp_req\n        # param vals go directly in imp_req\n        rules_param_vals_dict = md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {})\n        imp_req = CatalogReader._get_imp_req_for_control(ssp, control_id)\n        for comp_name, param_dict_list in rules_param_vals_dict.items():\n            for param_dict in as_list(param_dict_list):\n                if const.SSP_VALUES in param_dict:\n                    param_dict['values'] = param_dict['ssp-values']\n                CatalogReader._insert_param_dict_in_imp_req(\n                    imp_req, param_dict, comp_name, md_header, comp_dict[comp_name].uuid\n                )\n        param_vals_dict = md_header.get(const.SET_PARAMS_TAG, {})\n        for param_id, param_dict in param_vals_dict.items():\n            if const.SSP_VALUES in param_dict:\n                CatalogReader._add_set_params_to_item(param_dict, imp_req, param_id)\n\n        CatalogReader._add_props_to_imp_req(control_id, part_label_to_id_map, md_header, imp_req)\n\n    @staticmethod\n    def read_ssp_md_content(\n        md_path: pathlib.Path,\n        ssp: ossp.SystemSecurityPlan,\n        comp_dict: Dict[str, generic.GenericComponent],\n        part_id_map_by_label: Dict[str, Dict[str, str]],\n        context: ControlContext\n    ) -> None:\n\"\"\"\n        Read md content into the ssp.\n\n        Args:\n            md_path: path to the catalog markdown\n            ssp: ssp in which to insert the md content\n            comp_dict: map of component name to component\n            part_id_map_by_label: map label to part_id of control\n            context: control context for the procedure\n\n        Notes:\n            The ssp should already contain info from the comp defs and this fills in selected content from md.\n            The only content read from md is:\n                ssp values in the comp def rules param vals of the header\n                ssp values in the set-params of the header\n                all prose for implementaton responses\n                all status values\n            ssp has components but may not have all needed imp reqs and bycomps\n            know controlid and comp name in comp_dict\n        \"\"\"\n        for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n            for control_file in group_path.glob('*.md'):\n                skip = False\n                for file in control_file.parents:\n                    if file.name == const.INHERITANCE_VIEW_DIR:\n                        skip = True\n                        break\n                if skip:\n                    continue\n\n                control_id = control_file.stem\n\n                md_header, control_comp_dict = CatalogReader._read_comp_info_from_md(control_file, context)\n\n                for comp_name, comp_info_dict in control_comp_dict.items():\n                    if comp_name not in comp_dict:\n                        err_msg = f'Control {control_id} references component {comp_name} not defined in a component-definition.'  # noqa E501\n                        # give added guidance if no comp defs were specified at command line\n                        if not context.comp_def_name_list:\n                            err_msg += '  Please specify the names of any component-definitions needed for assembly.'\n                        raise TrestleError(err_msg)\n                    CatalogReader._update_ssp_with_comp_info(\n                        ssp, control_id, comp_dict[comp_name], comp_info_dict, part_id_map_by_label\n                    )\n                CatalogReader._update_ssp_with_md_header(ssp, control_id, comp_dict, part_id_map_by_label, md_header)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.__init__","title":"__init__(self, catalog_interface) special","text":"

                                                                            Initialize catalog reader.

                                                                            Source code in trestle/core/catalog/catalog_reader.py
                                                                            def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog reader.\"\"\"\n    self._catalog_interface = catalog_interface\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_additional_content","title":"read_additional_content(self, md_path, required_sections_list, label_map, sections_dict, write_mode)","text":"

                                                                            Read all markdown controls and return list of alters plus control param dict and param sort map.

                                                                            Source code in trestle/core/catalog/catalog_reader.py
                                                                            def read_additional_content(\n    self,\n    md_path: pathlib.Path,\n    required_sections_list: List[str],\n    label_map: Dict[str, Dict[str, str]],\n    sections_dict: Dict[str, str],\n    write_mode: bool\n) -> Tuple[List[prof.Alter], Dict[str, Any], Dict[str, str]]:\n\"\"\"Read all markdown controls and return list of alters plus control param dict and param sort map.\"\"\"\n    alters_map: Dict[str, prof.Alter] = {}\n    final_param_dict: Dict[str, Any] = {}\n    param_sort_map: Dict[str, str] = {}\n    for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n        for control_file in group_path.glob('*.md'):\n            sort_id, control_alters, control_param_dict = ControlReader.read_editable_content(\n                control_file,\n                required_sections_list,\n                label_map,\n                sections_dict,\n                write_mode\n            )\n            alters_map[sort_id] = control_alters\n            for param_id, param_dict in control_param_dict.items():\n                # if profile_values are present, overwrite values with them\n                if const.PROFILE_VALUES in param_dict:\n                    if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                        if not write_mode and const.REPLACE_ME_PLACEHOLDER in param_dict[const.PROFILE_VALUES]:\n                            param_dict[const.PROFILE_VALUES].remove(const.REPLACE_ME_PLACEHOLDER)\n                        if param_dict[const.PROFILE_VALUES] != [] and param_dict[const.PROFILE_VALUES] is not None:\n                            param_dict[const.VALUES] = param_dict[const.PROFILE_VALUES]\n                    if not write_mode:\n                        param_dict.pop(const.PROFILE_VALUES)\n                # verifies if at control profile edition the param value origin was modified\n                # through the profile-param-value-origin tag\n                if const.PROFILE_PARAM_VALUE_ORIGIN in param_dict:\n                    if param_dict[const.PROFILE_PARAM_VALUE_ORIGIN] != const.REPLACE_ME_PLACEHOLDER:\n                        param_dict[const.PARAM_VALUE_ORIGIN] = param_dict[const.PROFILE_PARAM_VALUE_ORIGIN]\n                        param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                    else:\n                        # removes replace me placeholder and profile-param-value-origin as it was not modified\n                        param_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n                        # validates param-value-origin is in dict to remove it\n                        # because a value wasn\u00b4t provided and it shouldn\u00b4t be inheriting value from parent\n                        if const.PARAM_VALUE_ORIGIN in param_dict:\n                            param_dict.pop(const.PARAM_VALUE_ORIGIN)\n                final_param_dict[param_id] = param_dict\n                param_sort_map[param_id] = sort_id\n    new_alters: List[prof.Alter] = []\n    # fill the alters according to the control sorting order\n    for key in sorted(alters_map.keys()):\n        new_alters.extend(alters_map[key])\n    return new_alters, final_param_dict, param_sort_map\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_catalog_from_markdown","title":"read_catalog_from_markdown(self, md_path, set_parameters_flag)","text":"

                                                                            Read the groups and catalog controls from the given directory.

                                                                            This will overwrite the existing groups and controls in the catalog.

                                                                            Source code in trestle/core/catalog/catalog_reader.py
                                                                            def read_catalog_from_markdown(self, md_path: pathlib.Path, set_parameters_flag: bool) -> cat.Catalog:\n\"\"\"\n    Read the groups and catalog controls from the given directory.\n\n    This will overwrite the existing groups and controls in the catalog.\n    \"\"\"\n    id_map = CatalogInterface._get_group_ids_and_dirs(md_path)\n    groups: List[cat.Group] = []\n    # read each group dir\n    for group_id, group_dir in id_map.items():\n        control_list_raw = []\n        group_title = ''\n        # Need to get group title from at least one control in this directory\n        # All controls in dir should have same group title\n        # Set group title to the first one found and warn if different non-empty title appears\n        # Controls with empty group titles are tolerated but at least one title must be present or warning given\n        # The special group with no name that has the catalog as parent is just a list and has no title\n        for control_path in group_dir.glob('*.md'):\n            control, control_group_title = ControlReader.read_control(control_path, set_parameters_flag)\n            if control_group_title:\n                if group_title:\n                    if control_group_title != group_title:\n                        logger.warning(\n                            f'Control {control.id} group title {control_group_title} differs from {group_title}'\n                        )\n                else:\n                    group_title = control_group_title\n            control_list_raw.append(control)\n        control_list = sorted(control_list_raw, key=lambda control: ControlInterface.get_sort_id(control))\n        if group_id:\n            if not group_title:\n                logger.warning(\n                    f'No group title found in controls for group {group_id}.  The title will be recovered if assembling into an existing catalog with the group title defined.'  # noqa E501\n                )\n            new_group = cat.Group(id=group_id, title=group_title)\n            new_group.controls = none_if_empty(control_list)\n            groups.append(new_group)\n        else:\n            # if the list of controls has no group id it also has no title and is just the controls of the catalog\n            self._catalog_interface._catalog.controls = none_if_empty(control_list)\n    self._catalog_interface._catalog.groups = none_if_empty(groups)\n    self._catalog_interface._create_control_dict()\n    self._catalog_interface._catalog.params = none_if_empty(self._catalog_interface._catalog.params)\n    return self._catalog_interface._catalog\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_catalog_imp_reqs","title":"read_catalog_imp_reqs(md_path, context) staticmethod","text":"

                                                                            Read the full set of control implemented requirements from markdown.

                                                                            Parameters:

                                                                            Name Type Description Default md_path Path

                                                                            Path to the markdown control files, with directories for each group

                                                                            required context ControlContext

                                                                            Context for the operation

                                                                            required

                                                                            Returns:

                                                                            Type Description List[trestle.oscal.component.ImplementedRequirement]

                                                                            List of implemented requirements gathered from each control

                                                                            Notes

                                                                            As the controls are read into the catalog the needed components are added if not already available. avail_comps provides the mapping of component name to the actual component. This is only used during component assemble and only for updating one component

                                                                            Source code in trestle/core/catalog/catalog_reader.py
                                                                            @staticmethod\ndef read_catalog_imp_reqs(md_path: pathlib.Path, context: ControlContext) -> List[comp.ImplementedRequirement]:\n\"\"\"Read the full set of control implemented requirements from markdown.\n\n    Args:\n        md_path: Path to the markdown control files, with directories for each group\n        context: Context for the operation\n\n    Returns:\n        List of implemented requirements gathered from each control\n\n    Notes:\n        As the controls are read into the catalog the needed components are added if not already available.\n        avail_comps provides the mapping of component name to the actual component.\n        This is only used during component assemble and only for updating one component\n    \"\"\"\n    imp_req_map: Dict[str, comp.ImplementedRequirement] = {}\n    for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n        for control_file in group_path.glob('*.md'):\n            sort_id, imp_req = ControlReader.read_implemented_requirement(control_file, context)\n            imp_req_map[sort_id] = imp_req\n    return [imp_req_map[key] for key in sorted(imp_req_map.keys())]\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_reader/#trestle.core.catalog.catalog_reader.CatalogReader.read_ssp_md_content","title":"read_ssp_md_content(md_path, ssp, comp_dict, part_id_map_by_label, context) staticmethod","text":"

                                                                            Read md content into the ssp.

                                                                            Parameters:

                                                                            Name Type Description Default md_path Path

                                                                            path to the catalog markdown

                                                                            required ssp SystemSecurityPlan

                                                                            ssp in which to insert the md content

                                                                            required comp_dict Dict[str, trestle.core.generic_oscal.GenericComponent]

                                                                            map of component name to component

                                                                            required part_id_map_by_label Dict[str, Dict[str, str]]

                                                                            map label to part_id of control

                                                                            required context ControlContext

                                                                            control context for the procedure

                                                                            required

                                                                            Notes

                                                                            The ssp should already contain info from the comp defs and this fills in selected content from md. The only content read from md is: ssp values in the comp def rules param vals of the header ssp values in the set-params of the header all prose for implementaton responses all status values ssp has components but may not have all needed imp reqs and bycomps know controlid and comp name in comp_dict

                                                                            Source code in trestle/core/catalog/catalog_reader.py
                                                                            @staticmethod\ndef read_ssp_md_content(\n    md_path: pathlib.Path,\n    ssp: ossp.SystemSecurityPlan,\n    comp_dict: Dict[str, generic.GenericComponent],\n    part_id_map_by_label: Dict[str, Dict[str, str]],\n    context: ControlContext\n) -> None:\n\"\"\"\n    Read md content into the ssp.\n\n    Args:\n        md_path: path to the catalog markdown\n        ssp: ssp in which to insert the md content\n        comp_dict: map of component name to component\n        part_id_map_by_label: map label to part_id of control\n        context: control context for the procedure\n\n    Notes:\n        The ssp should already contain info from the comp defs and this fills in selected content from md.\n        The only content read from md is:\n            ssp values in the comp def rules param vals of the header\n            ssp values in the set-params of the header\n            all prose for implementaton responses\n            all status values\n        ssp has components but may not have all needed imp reqs and bycomps\n        know controlid and comp name in comp_dict\n    \"\"\"\n    for group_path in CatalogInterface._get_group_ids_and_dirs(md_path).values():\n        for control_file in group_path.glob('*.md'):\n            skip = False\n            for file in control_file.parents:\n                if file.name == const.INHERITANCE_VIEW_DIR:\n                    skip = True\n                    break\n            if skip:\n                continue\n\n            control_id = control_file.stem\n\n            md_header, control_comp_dict = CatalogReader._read_comp_info_from_md(control_file, context)\n\n            for comp_name, comp_info_dict in control_comp_dict.items():\n                if comp_name not in comp_dict:\n                    err_msg = f'Control {control_id} references component {comp_name} not defined in a component-definition.'  # noqa E501\n                    # give added guidance if no comp defs were specified at command line\n                    if not context.comp_def_name_list:\n                        err_msg += '  Please specify the names of any component-definitions needed for assembly.'\n                    raise TrestleError(err_msg)\n                CatalogReader._update_ssp_with_comp_info(\n                    ssp, control_id, comp_dict[comp_name], comp_info_dict, part_id_map_by_label\n                )\n            CatalogReader._update_ssp_with_md_header(ssp, control_id, comp_dict, part_id_map_by_label, md_header)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/","title":"catalog_writer","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer","title":"trestle.core.catalog.catalog_writer","text":"

                                                                            Provide interface to write OSCAL catalog to markdown.

                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter","title":" CatalogWriter ","text":"

                                                                            Catalog writer.

                                                                            Catalog writer handles all operation related to writing catalog to markdown.

                                                                            Source code in trestle/core/catalog/catalog_writer.py
                                                                            class CatalogWriter():\n\"\"\"\n    Catalog writer.\n\n    Catalog writer handles all operation related to writing\n    catalog to markdown.\n    \"\"\"\n\n    def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog writer.\"\"\"\n        self._catalog_interface = catalog_interface\n\n    def write_catalog_as_profile_markdown(\n        self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]], md_alters: List[prof.Alter]\n    ) -> None:\n\"\"\"Write out the catalog as profile markdown.\"\"\"\n        # Get the list of params for this profile from its set_params\n        # this is just from the set_params\n        profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n\n        # write out the controls\n        for control in self._catalog_interface.get_all_controls_from_catalog(True):\n            # here we do special handling of how set-parameters merge with the yaml header\n            new_context = ControlContext.clone(context)\n            new_context.merged_header = {}\n\n            new_context = self._add_inherited_props_to_header(new_context, control.id)\n\n            # get all params and vals for this control from the resolved profile catalog with block adds in effect\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n\n            if set_param_dict:\n                self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n            elif const.SET_PARAMS_TAG in new_context.merged_header:\n                # need to cull any params that are not in control\n                pop_list: List[str] = []\n                for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                    if key not in control_param_dict:\n                        pop_list.append(key)\n                for pop in pop_list:\n                    new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n            found_control_alters = [alter for alter in md_alters if alter.control_id == control.id]\n\n            self._write_control_into_dir(new_context, control, part_id_map, found_control_alters)\n\n    def _add_inherited_props_to_header(self, context: ControlContext, control_id: str) -> ControlContext:\n\"\"\"Add inherited props to the merged header under inherited tag.\"\"\"\n        if context.inherited_props:\n            inherited_props = context.inherited_props.get(control_id, None)\n            if inherited_props:\n                # build set in order of list so that duplicates will have final value stick, then convert to list\n                unique_props = list({prop['name']: prop for prop in inherited_props}.values())\n                context.merged_header[const.TRESTLE_INHERITED_PROPS_TAG] = unique_props\n\n        return context\n\n    def _add_set_params_from_cli_yaml_header_to_header(\n        self, context: ControlContext, set_param_dict: Dict[str, str], control_param_dict: Dict[str, common.Parameter]\n    ):\n\"\"\"\n        Add set parameters from the provided cli yaml header to the merged header.\n\n        If overwrite-header-value flag is given\n            - Set-parameters in set_param_dict will be overwritten with those in cli yaml header\n            - No new params from the cli yaml header will be added <- TODO: Is this correct?\n        If ohv flag is NOT given :\n            - Set-parameters from the cli yaml header will be added\n            - Will not overwrite params that are already in set_param_dict\n        \"\"\"\n        if const.SET_PARAMS_TAG not in context.cli_yaml_header:\n            context.cli_yaml_header[const.SET_PARAMS_TAG] = {}\n\n        if context.cli_yaml_header:\n            if context.overwrite_header_values:\n                # update the control params with new values\n                for key, value in context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict:\n                        set_param_dict[key] = value\n            else:\n                # update the control params with any values in yaml header not set in control\n                # need to maintain order in the set_param_dict\n                for key, value in context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict and key not in set_param_dict:\n                        set_param_dict[key] = value\n        context.merged_header[const.SET_PARAMS_TAG] = set_param_dict\n\n    def _construct_set_parameters_dict(\n        self,\n        profile_set_param_dict: Dict[str, common.Parameter],\n        control_param_dict: Dict[str, Dict[str, Any]],\n        context: ControlContext\n    ) -> Dict[str, Dict[str, Any]]:\n\"\"\"\n        Build set-parameters dictionary from the given profile.modify.set-parameters and control.params.\n\n        Resulting dictionary will have:\n        - All parameters from the control where:\n            - If control_param in profile.modify.set_params:\n                - Display name (if exists) - from profile\n                - Profile-values - from profile\n                - Values - from control\n            - If control_param is not in profile.modify.set_params:\n                - Values - from control\n        \"\"\"\n        set_param_dict: Dict[str, Dict[str, Any]] = {}\n        for param_id, param_dict in control_param_dict.items():\n            # if the param is in the full_param_dict, load its contents first and mark as profile-values\n            display_name = ''\n            param_value_origin, _ = CatalogInterface._get_param_value_origin_and_ns(param_dict)\n            prof_param_value_origin = ''\n            if param_id in profile_set_param_dict:\n                # get the param from the profile set_param\n                param = profile_set_param_dict[param_id]\n                display_name, _ = CatalogInterface._get_display_name_and_ns(param)\n                prof_param_value_origin, _ = CatalogInterface._get_param_value_origin_and_ns(param)\n                # assign its contents to the dict\n                new_dict = ModelUtils.parameter_to_dict(param, True)\n                if const.VALUES in new_dict:\n                    if context.purpose == ContextPurpose.PROFILE:\n                        new_dict[const.PROFILE_VALUES] = new_dict[const.VALUES]\n                        new_dict.pop(const.VALUES)\n                # validates if parent profile has param-value-origin field\n                if param_value_origin != '' and param_value_origin is not None:\n                    if context.purpose == ContextPurpose.PROFILE:\n                        new_dict[const.PARAM_VALUE_ORIGIN] = param_value_origin\n                # validates if current profile has param-value-origin field and\n                # adds it to prof-param-value-origin\n                if prof_param_value_origin != '' and prof_param_value_origin is not None:\n                    if context.purpose == ContextPurpose.PROFILE:\n                        if const.AGGREGATES not in [prop.name for prop in as_list(param.props)]:\n                            new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = prof_param_value_origin\n                else:\n                    if const.AGGREGATES not in [prop.name for prop in as_list(param.props)]:\n                        new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = const.REPLACE_ME_PLACEHOLDER\n                # then insert the original, incoming values as values\n                if param_id in control_param_dict:\n                    orig_param = control_param_dict[param_id]\n                    orig_dict = ModelUtils.parameter_to_dict(orig_param, True)\n                    # pull only the values from the actual control dict\n                    # all the other elements are from the profile set_param\n                    new_dict[const.VALUES] = orig_dict.get(const.VALUES, None)\n                    new_dict[const.GUIDELINES] = orig_dict.get(const.GUIDELINES, None)\n                    if new_dict[const.VALUES] is None:\n                        new_dict.pop(const.VALUES)\n                    if new_dict[const.GUIDELINES] is None:\n                        new_dict.pop(const.GUIDELINES)\n                    if const.AGGREGATES in [prop.name for prop in as_list(orig_param.props)]:\n                        new_dict.pop(const.PROFILE_PARAM_VALUE_ORIGIN)\n            else:\n                # if the profile doesnt change this param at all, show it in the header with values\n                tmp_dict = ModelUtils.parameter_to_dict(param_dict, True)\n                values = tmp_dict.get('values', None)\n                # if values are None then don\u00b4t display them in the markdown\n                if values is not None:\n                    new_dict = {\n                        'id': param_id,\n                        'values': values,\n                    }\n                else:\n                    new_dict = {\n                        'id': param_id,\n                    }\n                new_dict[const.PROFILE_VALUES] = [const.REPLACE_ME_PLACEHOLDER]\n                new_dict[const.PROFILE_PARAM_VALUE_ORIGIN] = const.REPLACE_ME_PLACEHOLDER\n            if param_value_origin is not None:\n                if context.purpose == ContextPurpose.PROFILE:\n                    new_dict[const.PARAM_VALUE_ORIGIN] = param_value_origin\n            new_dict.pop('id', None)\n            # validates if there are aggregated parameter values to the current parameter\n            aggregated_props = [prop for prop in as_list(param_dict.props) if prop.name == const.AGGREGATES]\n            if aggregated_props != []:\n                props_to_add = []\n                for prop in aggregated_props:\n                    props_to_add.append(prop.value)\n                new_dict[const.AGGREGATES] = props_to_add\n                new_dict.pop(const.PROFILE_VALUES, None)\n            alt_identifier = [prop for prop in as_list(param_dict.props) if prop.name == const.ALT_IDENTIFIER]\n            if alt_identifier != []:\n                new_dict[const.ALT_IDENTIFIER] = alt_identifier[0].value\n            # adds display name, if no display name then do not add to dict\n            if display_name != '' and display_name is not None:\n                new_dict[const.DISPLAY_NAME] = display_name\n            key_order = (\n                const.LABEL,\n                const.GUIDELINES,\n                const.VALUES,\n                const.AGGREGATES,\n                const.ALT_IDENTIFIER,\n                const.DISPLAY_NAME,\n                const.PROFILE_VALUES,\n                const.PARAM_VALUE_ORIGIN,\n                const.PROFILE_PARAM_VALUE_ORIGIN\n            )\n            ordered_dict = {k: new_dict[k] for k in key_order if k in new_dict.keys()}\n            set_param_dict[param_id] = ordered_dict\n\n        return set_param_dict\n\n    @staticmethod\n    def _fixup_param_dicts(context: ControlContext) -> None:\n\"\"\"Merge info in the rules params dict and the rules param vals dict.\"\"\"\n        for comp_name, comp_dict in context.rules_params_dict.items():\n            rules_dict = context.rules_dict.get(comp_name, {})\n            for rule_id, params_list in comp_dict.items():\n                for param in params_list:\n                    rule_name = deep_get(rules_dict, [rule_id, 'name'], 'unknown_rule_name')\n                    param[const.HEADER_RULE_ID] = rule_name\n\n    def write_catalog_as_ssp_markdown(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"\n        Write out the catalog as component markdown.\n\n        Already have resolved profile catalog, but with no setparams from compdefs\n        Load all control level rules and param values based on compdefs and profile values\n\n        In memory:\n        for each compdef:\n            for each comp:\n                load top level rules\n                for each control_imp:\n                    load set-params\n                    for each imp_req (bound to 1 control):\n                        load set-params\n                        load control level rules and status\n                        load part level rules and status\n                        add as compinfo to control comp_dict\n\n        \"\"\"\n        # generate rule and param info from the components\n        self._catalog_interface.generate_control_rule_info(part_id_map, context)\n\n        # now have all rules in context.rules_dict and all rules_params in context.rules_params_dict\n        # all set-params per component for each control are in the cat interface\n        # all comp-infos by control and part are in the cat interface\n        #\n        # can now write out catalog and pull from the markdown:\n        # header for param values to set during assem\n        # prose and status for This System\n        # status for all parts that still have rules\n\n        CatalogWriter._fixup_param_dicts(context)\n\n        # remove items left after above loop\n        context.component = None\n        context.comp_name = None\n\n        # get param_dict of set_params in profile\n        profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n        catalog_merger = CatalogMerger(self._catalog_interface)\n        for control in self._catalog_interface.get_all_controls_from_dict():\n            control_id = control.id\n            context.comp_dict = self._catalog_interface._control_comp_dicts.get(control_id, {})\n            control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control_id)\n            control_file_path.parent.mkdir(exist_ok=True, parents=True)\n            # the catalog interface is from the resolved profile catalog\n            control = self._catalog_interface.get_control(control_id)\n            _, group_title, _ = self._catalog_interface.get_group_info_by_control(control_id)\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n            new_context = ControlContext.clone(context)\n\n            if set_param_dict:\n                self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n            elif const.SET_PARAMS_TAG in new_context.merged_header:\n                # need to cull any params that are not in control\n                pop_list: List[str] = []\n                for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                    if key not in control_param_dict:\n                        pop_list.append(key)\n                for pop in pop_list:\n                    new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n            # merge the md_header and md_comp_dict with info in cat_interface for this control in new_context\n            catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n            if const.COMP_DEF_RULES_PARAM_VALS_TAG in new_context.merged_header:\n                for _, param_list in new_context.merged_header[const.COMP_DEF_RULES_PARAM_VALS_TAG].items():\n                    for param_dict in param_list:\n                        param_dict.pop(const.HEADER_RULE_ID, None)\n\n            control_writer = ControlWriter()\n            control_writer.write_control_for_editing(\n                new_context, control, control_file_path.parent, group_title, part_id_map, []\n            )\n\n    def write_catalog_as_component_markdown(\n        self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]\n    ) -> None:\n\"\"\"Write out the catalog as component markdown.\"\"\"\n        context.rules_dict = {}\n        context.rules_params_dict = {}\n\n        def _update_values(set_param: comp.SetParameter, control_param_dict) -> None:\n            # set the param values based on the control_param_dict if available\n            if set_param.param_id in control_param_dict:\n                control_param_dict[set_param.param_id] = set_param\n\n        control_ids_in_comp_imp = [\n            imp_req.control_id for imp_req in as_list(context.control_implementation.implemented_requirements)\n        ]\n\n        missing_controls = set(control_ids_in_comp_imp).difference(self._catalog_interface.get_control_ids())\n        if missing_controls:\n            logger.warning(f'Component {context.comp_name} references controls {missing_controls} not in profile.')\n\n        # get top level rule info applying to all controls\n        comp_rules_dict, comp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(context.component)  # noqa E501\n        context.rules_dict[context.comp_name] = comp_rules_dict\n        context.rules_params_dict[context.comp_name] = comp_rules_params_dict\n        for control_imp in as_list(context.component.control_implementations):\n            control_imp_rules_dict, control_imp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)  # noqa E501\n            context.rules_dict[context.comp_name].update(control_imp_rules_dict)\n            comp_rules_params_dict = context.rules_params_dict.get(context.comp_name, {})\n            comp_rules_params_dict.update(control_imp_rules_params_dict)\n            context.rules_params_dict[context.comp_name].update(comp_rules_params_dict)\n            ci_set_params = ControlInterface.get_set_params_from_item(control_imp)\n            for imp_req in as_list(control_imp.implemented_requirements):\n                control_part_id_map = part_id_map.get(imp_req.control_id, {})\n                control_rules, statement_rules, _ = ControlInterface.get_rule_list_for_imp_req(imp_req)\n                if control_rules or statement_rules:\n                    if control_rules:\n                        status = ControlInterface.get_status_from_props(imp_req)\n                        comp_info = ComponentImpInfo(imp_req.description, control_rules, [], status)\n                        self._catalog_interface.add_comp_info(imp_req.control_id, context.comp_name, '', comp_info)\n                    set_params = copy.deepcopy(ci_set_params)\n                    set_params.update(ControlInterface.get_set_params_from_item(imp_req))\n                    for set_param in set_params.values():\n                        self._catalog_interface.add_comp_set_param(imp_req.control_id, context.comp_name, set_param)\n                    for statement in as_list(imp_req.statements):\n                        rule_list, _ = ControlInterface.get_rule_list_for_item(statement)\n                        if rule_list:\n                            status = ControlInterface.get_status_from_props(statement)\n                            if statement.statement_id not in control_part_id_map:\n                                label = statement.statement_id\n                                logger.warning(\n                                    f'No statement label found for statement id {label}.  Defaulting to {label}.'\n                                )\n                            else:\n                                label = control_part_id_map[statement.statement_id]\n                            comp_info = ComponentImpInfo(statement.description, rule_list, [], status)\n                            self._catalog_interface.add_comp_info(\n                                imp_req.control_id, context.comp_name, label, comp_info\n                            )\n\n        catalog_merger = CatalogMerger(self._catalog_interface)\n\n        for control in self._catalog_interface.get_all_controls_from_catalog(True):\n            if control.id in control_ids_in_comp_imp:\n                context.comp_dict = self._catalog_interface.get_comp_info(control.id)\n                new_context = ControlContext.clone(context)\n                # get the resolved catalog values for the control params\n                control_param_dict = ControlInterface.get_control_param_dict(control, False)\n                # update them with values in the ci\n                for set_param in as_list(new_context.control_implementation.set_parameters):\n                    _update_values(set_param, control_param_dict)\n                # update them with values in the imp_req\n                for imp_req in as_list(new_context.control_implementation.implemented_requirements):\n                    if imp_req.control_id == control.id:\n                        for set_param in as_list(imp_req.set_parameters):\n                            _update_values(set_param, control_param_dict)\n\n                # insert the param values into the header\n                if control_param_dict:\n                    new_context.merged_header[const.PARAM_VALUES_TAG] = {}\n                    for key, param in control_param_dict.items():\n                        new_context.merged_header[const.PARAM_VALUES_TAG][key] = none_if_empty(\n                            ControlInterface._param_values_as_str_list(param)\n                        )\n                # merge the md_header and md_comp_dict with info in cat_interface for this control\n                control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control.id)\n                catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n                self._write_control_into_dir(new_context, control, part_id_map, [])\n\n    def write_catalog_as_catalog(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"Write the catalog as a simple catalog.\"\"\"\n        # write out the controls\n        for control in self._catalog_interface.get_all_controls_from_catalog(True):\n            # here we do special handling of how set-parameters merge with the yaml header\n            new_context = ControlContext.clone(context)\n\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            set_param_dict: Dict[str, str] = {}\n            for param_id, param_dict in control_param_dict.items():\n                tmp_dict = ModelUtils.parameter_to_dict(param_dict, True)\n                values = tmp_dict.get('values', None)\n                new_dict = {'values': values}\n                set_param_dict[param_id] = new_dict\n            if set_param_dict:\n                if const.SET_PARAMS_TAG not in new_context.cli_yaml_header:\n                    new_context.cli_yaml_header[const.SET_PARAMS_TAG] = {}\n                if new_context.overwrite_header_values:\n                    # update the control params with new values\n                    for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                        if key in control_param_dict:\n                            set_param_dict[key] = value\n                else:\n                    # update the control params with any values in yaml header not set in control\n                    # need to maintain order in the set_param_dict\n                    for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                        if key in control_param_dict and key not in set_param_dict:\n                            set_param_dict[key] = value\n                new_context.cli_yaml_header[const.SET_PARAMS_TAG] = set_param_dict\n            elif const.SET_PARAMS_TAG in new_context.cli_yaml_header:\n                # need to cull any params that are not in control\n                pop_list: List[str] = []\n                for key in new_context.cli_yaml_header[const.SET_PARAMS_TAG].keys():\n                    if key not in control_param_dict:\n                        pop_list.append(key)\n                for pop in pop_list:\n                    new_context.cli_yaml_header[const.SET_PARAMS_TAG].pop(pop)\n\n            self._write_control_into_dir(new_context, control, part_id_map, [])\n\n    def _write_control_into_dir(\n        self,\n        context: ControlContext,\n        control: cat.Control,\n        part_id_map: Dict[str, Dict[str, str]],\n        found_control_alters: List[prof.Alter]\n    ):\n        # we need to create the dir structure on demand because we don't know a priori what groups are included\n        _, group_title, _ = self._catalog_interface.get_group_info_by_control(control.id)\n        group_dir = context.md_root\n        control_path = self._catalog_interface.get_control_path(control.id)\n        for sub_dir in control_path:\n            group_dir = group_dir / sub_dir\n            if not group_dir.exists():\n                group_dir.mkdir(parents=True, exist_ok=True)\n\n        writer = ControlWriter()\n        writer.write_control_for_editing(context, control, group_dir, group_title, part_id_map, found_control_alters)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.__init__","title":"__init__(self, catalog_interface) special","text":"

                                                                            Initialize catalog writer.

                                                                            Source code in trestle/core/catalog/catalog_writer.py
                                                                            def __init__(self, catalog_interface: CatalogInterface):\n\"\"\"Initialize catalog writer.\"\"\"\n    self._catalog_interface = catalog_interface\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_catalog","title":"write_catalog_as_catalog(self, context, part_id_map)","text":"

                                                                            Write the catalog as a simple catalog.

                                                                            Source code in trestle/core/catalog/catalog_writer.py
                                                                            def write_catalog_as_catalog(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"Write the catalog as a simple catalog.\"\"\"\n    # write out the controls\n    for control in self._catalog_interface.get_all_controls_from_catalog(True):\n        # here we do special handling of how set-parameters merge with the yaml header\n        new_context = ControlContext.clone(context)\n\n        control_param_dict = ControlInterface.get_control_param_dict(control, False)\n        set_param_dict: Dict[str, str] = {}\n        for param_id, param_dict in control_param_dict.items():\n            tmp_dict = ModelUtils.parameter_to_dict(param_dict, True)\n            values = tmp_dict.get('values', None)\n            new_dict = {'values': values}\n            set_param_dict[param_id] = new_dict\n        if set_param_dict:\n            if const.SET_PARAMS_TAG not in new_context.cli_yaml_header:\n                new_context.cli_yaml_header[const.SET_PARAMS_TAG] = {}\n            if new_context.overwrite_header_values:\n                # update the control params with new values\n                for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict:\n                        set_param_dict[key] = value\n            else:\n                # update the control params with any values in yaml header not set in control\n                # need to maintain order in the set_param_dict\n                for key, value in new_context.cli_yaml_header[const.SET_PARAMS_TAG].items():\n                    if key in control_param_dict and key not in set_param_dict:\n                        set_param_dict[key] = value\n            new_context.cli_yaml_header[const.SET_PARAMS_TAG] = set_param_dict\n        elif const.SET_PARAMS_TAG in new_context.cli_yaml_header:\n            # need to cull any params that are not in control\n            pop_list: List[str] = []\n            for key in new_context.cli_yaml_header[const.SET_PARAMS_TAG].keys():\n                if key not in control_param_dict:\n                    pop_list.append(key)\n            for pop in pop_list:\n                new_context.cli_yaml_header[const.SET_PARAMS_TAG].pop(pop)\n\n        self._write_control_into_dir(new_context, control, part_id_map, [])\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_component_markdown","title":"write_catalog_as_component_markdown(self, context, part_id_map)","text":"

                                                                            Write out the catalog as component markdown.

                                                                            Source code in trestle/core/catalog/catalog_writer.py
                                                                            def write_catalog_as_component_markdown(\n    self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]\n) -> None:\n\"\"\"Write out the catalog as component markdown.\"\"\"\n    context.rules_dict = {}\n    context.rules_params_dict = {}\n\n    def _update_values(set_param: comp.SetParameter, control_param_dict) -> None:\n        # set the param values based on the control_param_dict if available\n        if set_param.param_id in control_param_dict:\n            control_param_dict[set_param.param_id] = set_param\n\n    control_ids_in_comp_imp = [\n        imp_req.control_id for imp_req in as_list(context.control_implementation.implemented_requirements)\n    ]\n\n    missing_controls = set(control_ids_in_comp_imp).difference(self._catalog_interface.get_control_ids())\n    if missing_controls:\n        logger.warning(f'Component {context.comp_name} references controls {missing_controls} not in profile.')\n\n    # get top level rule info applying to all controls\n    comp_rules_dict, comp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(context.component)  # noqa E501\n    context.rules_dict[context.comp_name] = comp_rules_dict\n    context.rules_params_dict[context.comp_name] = comp_rules_params_dict\n    for control_imp in as_list(context.component.control_implementations):\n        control_imp_rules_dict, control_imp_rules_params_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)  # noqa E501\n        context.rules_dict[context.comp_name].update(control_imp_rules_dict)\n        comp_rules_params_dict = context.rules_params_dict.get(context.comp_name, {})\n        comp_rules_params_dict.update(control_imp_rules_params_dict)\n        context.rules_params_dict[context.comp_name].update(comp_rules_params_dict)\n        ci_set_params = ControlInterface.get_set_params_from_item(control_imp)\n        for imp_req in as_list(control_imp.implemented_requirements):\n            control_part_id_map = part_id_map.get(imp_req.control_id, {})\n            control_rules, statement_rules, _ = ControlInterface.get_rule_list_for_imp_req(imp_req)\n            if control_rules or statement_rules:\n                if control_rules:\n                    status = ControlInterface.get_status_from_props(imp_req)\n                    comp_info = ComponentImpInfo(imp_req.description, control_rules, [], status)\n                    self._catalog_interface.add_comp_info(imp_req.control_id, context.comp_name, '', comp_info)\n                set_params = copy.deepcopy(ci_set_params)\n                set_params.update(ControlInterface.get_set_params_from_item(imp_req))\n                for set_param in set_params.values():\n                    self._catalog_interface.add_comp_set_param(imp_req.control_id, context.comp_name, set_param)\n                for statement in as_list(imp_req.statements):\n                    rule_list, _ = ControlInterface.get_rule_list_for_item(statement)\n                    if rule_list:\n                        status = ControlInterface.get_status_from_props(statement)\n                        if statement.statement_id not in control_part_id_map:\n                            label = statement.statement_id\n                            logger.warning(\n                                f'No statement label found for statement id {label}.  Defaulting to {label}.'\n                            )\n                        else:\n                            label = control_part_id_map[statement.statement_id]\n                        comp_info = ComponentImpInfo(statement.description, rule_list, [], status)\n                        self._catalog_interface.add_comp_info(\n                            imp_req.control_id, context.comp_name, label, comp_info\n                        )\n\n    catalog_merger = CatalogMerger(self._catalog_interface)\n\n    for control in self._catalog_interface.get_all_controls_from_catalog(True):\n        if control.id in control_ids_in_comp_imp:\n            context.comp_dict = self._catalog_interface.get_comp_info(control.id)\n            new_context = ControlContext.clone(context)\n            # get the resolved catalog values for the control params\n            control_param_dict = ControlInterface.get_control_param_dict(control, False)\n            # update them with values in the ci\n            for set_param in as_list(new_context.control_implementation.set_parameters):\n                _update_values(set_param, control_param_dict)\n            # update them with values in the imp_req\n            for imp_req in as_list(new_context.control_implementation.implemented_requirements):\n                if imp_req.control_id == control.id:\n                    for set_param in as_list(imp_req.set_parameters):\n                        _update_values(set_param, control_param_dict)\n\n            # insert the param values into the header\n            if control_param_dict:\n                new_context.merged_header[const.PARAM_VALUES_TAG] = {}\n                for key, param in control_param_dict.items():\n                    new_context.merged_header[const.PARAM_VALUES_TAG][key] = none_if_empty(\n                        ControlInterface._param_values_as_str_list(param)\n                    )\n            # merge the md_header and md_comp_dict with info in cat_interface for this control\n            control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control.id)\n            catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n            self._write_control_into_dir(new_context, control, part_id_map, [])\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_profile_markdown","title":"write_catalog_as_profile_markdown(self, context, part_id_map, md_alters)","text":"

                                                                            Write out the catalog as profile markdown.

                                                                            Source code in trestle/core/catalog/catalog_writer.py
                                                                            def write_catalog_as_profile_markdown(\n    self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]], md_alters: List[prof.Alter]\n) -> None:\n\"\"\"Write out the catalog as profile markdown.\"\"\"\n    # Get the list of params for this profile from its set_params\n    # this is just from the set_params\n    profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n\n    # write out the controls\n    for control in self._catalog_interface.get_all_controls_from_catalog(True):\n        # here we do special handling of how set-parameters merge with the yaml header\n        new_context = ControlContext.clone(context)\n        new_context.merged_header = {}\n\n        new_context = self._add_inherited_props_to_header(new_context, control.id)\n\n        # get all params and vals for this control from the resolved profile catalog with block adds in effect\n        control_param_dict = ControlInterface.get_control_param_dict(control, False)\n        set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n\n        if set_param_dict:\n            self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n        elif const.SET_PARAMS_TAG in new_context.merged_header:\n            # need to cull any params that are not in control\n            pop_list: List[str] = []\n            for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                if key not in control_param_dict:\n                    pop_list.append(key)\n            for pop in pop_list:\n                new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n        found_control_alters = [alter for alter in md_alters if alter.control_id == control.id]\n\n        self._write_control_into_dir(new_context, control, part_id_map, found_control_alters)\n
                                                                            "},{"location":"api_reference/trestle.core.catalog.catalog_writer/#trestle.core.catalog.catalog_writer.CatalogWriter.write_catalog_as_ssp_markdown","title":"write_catalog_as_ssp_markdown(self, context, part_id_map)","text":"

                                                                            Write out the catalog as component markdown.

                                                                            Already have resolved profile catalog, but with no setparams from compdefs Load all control level rules and param values based on compdefs and profile values

                                                                            In memory: for each compdef: for each comp: load top level rules for each control_imp: load set-params for each imp_req (bound to 1 control): load set-params load control level rules and status load part level rules and status add as compinfo to control comp_dict

                                                                            Source code in trestle/core/catalog/catalog_writer.py
                                                                            def write_catalog_as_ssp_markdown(self, context: ControlContext, part_id_map: Dict[str, Dict[str, str]]) -> None:\n\"\"\"\n    Write out the catalog as component markdown.\n\n    Already have resolved profile catalog, but with no setparams from compdefs\n    Load all control level rules and param values based on compdefs and profile values\n\n    In memory:\n    for each compdef:\n        for each comp:\n            load top level rules\n            for each control_imp:\n                load set-params\n                for each imp_req (bound to 1 control):\n                    load set-params\n                    load control level rules and status\n                    load part level rules and status\n                    add as compinfo to control comp_dict\n\n    \"\"\"\n    # generate rule and param info from the components\n    self._catalog_interface.generate_control_rule_info(part_id_map, context)\n\n    # now have all rules in context.rules_dict and all rules_params in context.rules_params_dict\n    # all set-params per component for each control are in the cat interface\n    # all comp-infos by control and part are in the cat interface\n    #\n    # can now write out catalog and pull from the markdown:\n    # header for param values to set during assem\n    # prose and status for This System\n    # status for all parts that still have rules\n\n    CatalogWriter._fixup_param_dicts(context)\n\n    # remove items left after above loop\n    context.component = None\n    context.comp_name = None\n\n    # get param_dict of set_params in profile\n    profile_set_param_dict = CatalogInterface._get_full_profile_param_dict(context.profile)\n    catalog_merger = CatalogMerger(self._catalog_interface)\n    for control in self._catalog_interface.get_all_controls_from_dict():\n        control_id = control.id\n        context.comp_dict = self._catalog_interface._control_comp_dicts.get(control_id, {})\n        control_file_path = self._catalog_interface.get_control_file_path(context.md_root, control_id)\n        control_file_path.parent.mkdir(exist_ok=True, parents=True)\n        # the catalog interface is from the resolved profile catalog\n        control = self._catalog_interface.get_control(control_id)\n        _, group_title, _ = self._catalog_interface.get_group_info_by_control(control_id)\n        control_param_dict = ControlInterface.get_control_param_dict(control, False)\n        set_param_dict = self._construct_set_parameters_dict(profile_set_param_dict, control_param_dict, context)\n        new_context = ControlContext.clone(context)\n\n        if set_param_dict:\n            self._add_set_params_from_cli_yaml_header_to_header(new_context, set_param_dict, control_param_dict)\n\n        elif const.SET_PARAMS_TAG in new_context.merged_header:\n            # need to cull any params that are not in control\n            pop_list: List[str] = []\n            for key in new_context.merged_header[const.SET_PARAMS_TAG].keys():\n                if key not in control_param_dict:\n                    pop_list.append(key)\n            for pop in pop_list:\n                new_context.merged_header[const.SET_PARAMS_TAG].pop(pop)\n\n        # merge the md_header and md_comp_dict with info in cat_interface for this control in new_context\n        catalog_merger._merge_header_and_comp_dict(control, control_file_path, new_context)\n\n        if const.COMP_DEF_RULES_PARAM_VALS_TAG in new_context.merged_header:\n            for _, param_list in new_context.merged_header[const.COMP_DEF_RULES_PARAM_VALS_TAG].items():\n                for param_dict in param_list:\n                    param_dict.pop(const.HEADER_RULE_ID, None)\n\n        control_writer = ControlWriter()\n        control_writer.write_control_for_editing(\n            new_context, control, control_file_path.parent, group_title, part_id_map, []\n        )\n
                                                                            "},{"location":"api_reference/trestle.core.catalog_validator/","title":"catalog_validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator","title":"trestle.core.catalog_validator","text":"

                                                                            Validate catalog by confirming no duplicate param ids.

                                                                            "},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.CatalogValidator","title":" CatalogValidator (Validator) ","text":"

                                                                            Validator to confirm all param ids in catalog are unique.

                                                                            Source code in trestle/core/catalog_validator.py
                                                                            class CatalogValidator(Validator):\n\"\"\"Validator to confirm all param ids in catalog are unique.\"\"\"\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if it is not a catalog, or it is a catalog and its links are 1:1 with resources.\n        \"\"\"\n        if not isinstance(model, Catalog):\n            return True\n        catalog: Catalog = model\n        cat_interface = CatalogInterface(catalog)\n        param_ids = set()\n        for control in cat_interface.get_all_controls_from_dict():\n            for param in as_list(control.params):\n                if param.id in param_ids:\n                    logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n                    return False\n                param_ids.add(param.id)\n        for param_id in cat_interface.loose_param_dict.keys():\n            if param_id in param_ids:\n                logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n                return False\n        return True\n
                                                                            "},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.CatalogValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.catalog_validator/#trestle.core.catalog_validator.CatalogValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                                                            Test if the model is valid.

                                                                            Parameters:

                                                                            Name Type Description Default model ~TopLevelOscalModel

                                                                            A top level OSCAL model.

                                                                            required quiet bool

                                                                            Don't report msgs unless invalid.

                                                                            required

                                                                            Returns:

                                                                            Type Description True (valid) if it is not a catalog, or it is a catalog and its links are 1

                                                                            1 with resources.

                                                                            Source code in trestle/core/catalog_validator.py
                                                                            def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if it is not a catalog, or it is a catalog and its links are 1:1 with resources.\n    \"\"\"\n    if not isinstance(model, Catalog):\n        return True\n    catalog: Catalog = model\n    cat_interface = CatalogInterface(catalog)\n    param_ids = set()\n    for control in cat_interface.get_all_controls_from_dict():\n        for param in as_list(control.params):\n            if param.id in param_ids:\n                logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n                return False\n            param_ids.add(param.id)\n    for param_id in cat_interface.loose_param_dict.keys():\n        if param_id in param_ids:\n            logger.warning(f'Catalog has duplicated parameter id: {param.id} in control {control.id}')\n            return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.commands.add/","title":"add","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add","title":"trestle.core.commands.add","text":"

                                                                            Trestle Add Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add","title":" Add ","text":"

                                                                            Class supporting Add of an OSCAL object to a provided file based on element path.

                                                                            Examples of element paths: catalog.metadata catalog.controls.control assessment-results.results.

                                                                            The method first finds the parent model from the file and loads the file into the model. Then the method executes 'add' for each of the element paths specified. Add was originally its own command but has been incorporated into the Create command.

                                                                            Source code in trestle/core/commands/add.py
                                                                            class Add():\n\"\"\"\n    Class supporting Add of an OSCAL object to a provided file based on element path.\n\n    Examples of element paths:\n        catalog.metadata\n        catalog.controls.control\n        assessment-results.results.\n\n    The method first finds the parent model from the file and loads the file into the model.\n    Then the method executes 'add' for each of the element paths specified.\n    Add was originally its own command but has been incorporated into the Create command.\n    \"\"\"\n\n    def add_from_args(self, args: argparse.Namespace) -> int:\n\"\"\"Parse args for add element to file.\"\"\"\n        file_path = pathlib.Path(args.file).resolve()\n\n        # Get parent model and then load json into parent model\n        parent_model, _ = ModelUtils.get_stripped_model_type(file_path, args.trestle_root)\n        parent_object = parent_model.oscal_read(file_path)\n        parent_element = Element(parent_object, classname_to_alias(parent_model.__name__, AliasMode.JSON))\n\n        add_plan = Plan()\n        # Do _add for each element_path specified in args\n        element_paths: List[str] = args.element.split(',')\n        for elm_path_str in element_paths:\n            element_path = ElementPath(elm_path_str)\n            update_action, parent_element = self.add(element_path, parent_element, args.include_optional_fields)\n            add_plan.add_action(update_action)\n\n        create_action = CreatePathAction(file_path, True)\n        # this will output json or yaml based on type of input file\n        write_action = WriteFileAction(file_path, parent_element, FileContentType.to_content_type(file_path.suffix))\n\n        add_plan.add_action(create_action)\n        add_plan.add_action(write_action)\n\n        add_plan.execute()\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def add(element_path: ElementPath, parent_element: Element, include_optional: bool) -> Tuple[UpdateAction, Element]:\n\"\"\"For a element_path, add a child model to the parent_element of a given parent_model.\n\n        Args:\n            element_path: element path of the item to create within the model\n            parent_element: the parent element that will host the created element\n            include_optional: whether to create optional attributes in the created element\n\n        Notes:\n            First we find the child model at the specified element path and instantiate it with default values.\n            Then we check if there's already existing element at that path, in which case we append the child model\n            to the existing list of dict.\n            Then we set up an action plan to update the model (specified by file_path) in memory, create a file\n            at the same location and write the file.\n            We update the parent_element to prepare for next adds in the chain\n        \"\"\"\n        if '*' in element_path.get_full_path_parts():\n            raise err.TrestleError('trestle add does not support Wildcard element path.')\n        # Get child model\n        try:\n            child_model = element_path.get_type(type(parent_element.get()))\n\n            # Create child element with sample values\n            child_object = gens.generate_sample_model(child_model, include_optional=include_optional)\n\n            if parent_element.get_at(element_path) is not None:\n                # The element already exists\n                if type(parent_element.get_at(element_path)) is list:\n                    child_object = parent_element.get_at(element_path) + child_object\n                elif type(parent_element.get_at(element_path)) is dict:\n                    child_object = {**parent_element.get_at(element_path), **child_object}\n                else:\n                    raise err.TrestleError('Already exists and is not a list or dictionary.')\n\n        except Exception as e:\n            raise err.TrestleError(f'Bad element path. {str(e)}')\n\n        update_action = UpdateAction(\n            sub_element=child_object, dest_element=parent_element, sub_element_path=element_path\n        )\n        parent_element = parent_element.set_at(element_path, child_object)\n\n        return update_action, parent_element\n
                                                                            "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add.add","title":"add(element_path, parent_element, include_optional) staticmethod","text":"

                                                                            For a element_path, add a child model to the parent_element of a given parent_model.

                                                                            Parameters:

                                                                            Name Type Description Default element_path ElementPath

                                                                            element path of the item to create within the model

                                                                            required parent_element Element

                                                                            the parent element that will host the created element

                                                                            required include_optional bool

                                                                            whether to create optional attributes in the created element

                                                                            required

                                                                            Notes

                                                                            First we find the child model at the specified element path and instantiate it with default values. Then we check if there's already existing element at that path, in which case we append the child model to the existing list of dict. Then we set up an action plan to update the model (specified by file_path) in memory, create a file at the same location and write the file. We update the parent_element to prepare for next adds in the chain

                                                                            Source code in trestle/core/commands/add.py
                                                                            @staticmethod\ndef add(element_path: ElementPath, parent_element: Element, include_optional: bool) -> Tuple[UpdateAction, Element]:\n\"\"\"For a element_path, add a child model to the parent_element of a given parent_model.\n\n    Args:\n        element_path: element path of the item to create within the model\n        parent_element: the parent element that will host the created element\n        include_optional: whether to create optional attributes in the created element\n\n    Notes:\n        First we find the child model at the specified element path and instantiate it with default values.\n        Then we check if there's already existing element at that path, in which case we append the child model\n        to the existing list of dict.\n        Then we set up an action plan to update the model (specified by file_path) in memory, create a file\n        at the same location and write the file.\n        We update the parent_element to prepare for next adds in the chain\n    \"\"\"\n    if '*' in element_path.get_full_path_parts():\n        raise err.TrestleError('trestle add does not support Wildcard element path.')\n    # Get child model\n    try:\n        child_model = element_path.get_type(type(parent_element.get()))\n\n        # Create child element with sample values\n        child_object = gens.generate_sample_model(child_model, include_optional=include_optional)\n\n        if parent_element.get_at(element_path) is not None:\n            # The element already exists\n            if type(parent_element.get_at(element_path)) is list:\n                child_object = parent_element.get_at(element_path) + child_object\n            elif type(parent_element.get_at(element_path)) is dict:\n                child_object = {**parent_element.get_at(element_path), **child_object}\n            else:\n                raise err.TrestleError('Already exists and is not a list or dictionary.')\n\n    except Exception as e:\n        raise err.TrestleError(f'Bad element path. {str(e)}')\n\n    update_action = UpdateAction(\n        sub_element=child_object, dest_element=parent_element, sub_element_path=element_path\n    )\n    parent_element = parent_element.set_at(element_path, child_object)\n\n    return update_action, parent_element\n
                                                                            "},{"location":"api_reference/trestle.core.commands.add/#trestle.core.commands.add.Add.add_from_args","title":"add_from_args(self, args)","text":"

                                                                            Parse args for add element to file.

                                                                            Source code in trestle/core/commands/add.py
                                                                            def add_from_args(self, args: argparse.Namespace) -> int:\n\"\"\"Parse args for add element to file.\"\"\"\n    file_path = pathlib.Path(args.file).resolve()\n\n    # Get parent model and then load json into parent model\n    parent_model, _ = ModelUtils.get_stripped_model_type(file_path, args.trestle_root)\n    parent_object = parent_model.oscal_read(file_path)\n    parent_element = Element(parent_object, classname_to_alias(parent_model.__name__, AliasMode.JSON))\n\n    add_plan = Plan()\n    # Do _add for each element_path specified in args\n    element_paths: List[str] = args.element.split(',')\n    for elm_path_str in element_paths:\n        element_path = ElementPath(elm_path_str)\n        update_action, parent_element = self.add(element_path, parent_element, args.include_optional_fields)\n        add_plan.add_action(update_action)\n\n    create_action = CreatePathAction(file_path, True)\n    # this will output json or yaml based on type of input file\n    write_action = WriteFileAction(file_path, parent_element, FileContentType.to_content_type(file_path.suffix))\n\n    add_plan.add_action(create_action)\n    add_plan.add_action(write_action)\n\n    add_plan.execute()\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.assemble/","title":"assemble","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble","title":"trestle.core.commands.assemble","text":"

                                                                            Trestle Assemble Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd","title":" AssembleCmd (CommandPlusDocs) ","text":"

                                                                            Assemble all subcomponents from a specified trestle model into a single JSON/YAML file under dist.

                                                                            Source code in trestle/core/commands/assemble.py
                                                                            class AssembleCmd(CommandPlusDocs):\n\"\"\"Assemble all subcomponents from a specified trestle model into a single JSON/YAML file under dist.\"\"\"\n\n    name = 'assemble'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('model', help='', choices=const.MODEL_TYPE_LIST)\n        self.add_argument('-n', '--name', help='Name of a single model to assemble.')\n        self.add_argument('-t', '--type', action='store_true', help='Assemble all models of the given type.')\n        self.add_argument(\n            '-x', '--extension', help='Type of file output.', choices=['json', 'yaml', 'yml'], default='json'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            return self.assemble_model(args.model, args)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while assembling OSCAL model')\n\n    @classmethod\n    def assemble_model(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"Assemble a top level OSCAL model within the trestle dist directory.\"\"\"\n        log.set_log_level_from_args(args)\n        logger.info(f'Assembling models of type {model_alias}.')\n\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n        if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n            raise TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n        model_names = []\n        if args.name:\n            model_names = [args.name]\n            logger.info(f'Assembling single model of type {model_alias}: {args.name}.')\n        else:\n            model_names = ModelUtils.get_models_of_type(model_alias, trestle_root)\n            nmodels = len(model_names)\n            logger.info(f'Assembling {nmodels} found models of type {model_alias}.')\n        if len(model_names) == 0:\n            logger.info(f'No models found to assemble of type {model_alias}.')\n            return CmdReturnCodes.SUCCESS.value\n\n        for model_name in model_names:\n            # contruct path to the model file name\n            root_model_dir = trestle_root / ModelUtils.model_type_to_model_dir(model_alias)\n\n            model_file_type = file_utils.get_contextual_file_type(root_model_dir / model_name)\n\n            model_file_name = f'{model_alias}{FileContentType.to_file_extension(model_file_type)}'\n            root_model_filepath = root_model_dir / model_name / model_file_name\n\n            if not root_model_filepath.exists():\n                raise TrestleError(f'No top level model file at {root_model_dir}')\n\n            assembled_model = load_validate_model_path(args.trestle_root, root_model_filepath)\n            plural_alias = ModelUtils.model_type_to_model_dir(model_alias)\n\n            assembled_model_dir = trestle_root / const.TRESTLE_DIST_DIR / plural_alias\n\n            assembled_model_filepath = assembled_model_dir / f'{model_name}.{args.extension}'\n\n            plan = Plan()\n            plan.add_action(CreatePathAction(assembled_model_filepath, True))\n            plan.add_action(\n                WriteFileAction(\n                    assembled_model_filepath,\n                    Element(assembled_model),\n                    FileContentType.to_content_type(f'.{args.extension}')\n                )\n            )\n\n            plan.execute()\n\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.assemble/#trestle.core.commands.assemble.AssembleCmd.assemble_model","title":"assemble_model(model_alias, args) classmethod","text":"

                                                                            Assemble a top level OSCAL model within the trestle dist directory.

                                                                            Source code in trestle/core/commands/assemble.py
                                                                            @classmethod\ndef assemble_model(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"Assemble a top level OSCAL model within the trestle dist directory.\"\"\"\n    log.set_log_level_from_args(args)\n    logger.info(f'Assembling models of type {model_alias}.')\n\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n    if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n        raise TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n    model_names = []\n    if args.name:\n        model_names = [args.name]\n        logger.info(f'Assembling single model of type {model_alias}: {args.name}.')\n    else:\n        model_names = ModelUtils.get_models_of_type(model_alias, trestle_root)\n        nmodels = len(model_names)\n        logger.info(f'Assembling {nmodels} found models of type {model_alias}.')\n    if len(model_names) == 0:\n        logger.info(f'No models found to assemble of type {model_alias}.')\n        return CmdReturnCodes.SUCCESS.value\n\n    for model_name in model_names:\n        # contruct path to the model file name\n        root_model_dir = trestle_root / ModelUtils.model_type_to_model_dir(model_alias)\n\n        model_file_type = file_utils.get_contextual_file_type(root_model_dir / model_name)\n\n        model_file_name = f'{model_alias}{FileContentType.to_file_extension(model_file_type)}'\n        root_model_filepath = root_model_dir / model_name / model_file_name\n\n        if not root_model_filepath.exists():\n            raise TrestleError(f'No top level model file at {root_model_dir}')\n\n        assembled_model = load_validate_model_path(args.trestle_root, root_model_filepath)\n        plural_alias = ModelUtils.model_type_to_model_dir(model_alias)\n\n        assembled_model_dir = trestle_root / const.TRESTLE_DIST_DIR / plural_alias\n\n        assembled_model_filepath = assembled_model_dir / f'{model_name}.{args.extension}'\n\n        plan = Plan()\n        plan.add_action(CreatePathAction(assembled_model_filepath, True))\n        plan.add_action(\n            WriteFileAction(\n                assembled_model_filepath,\n                Element(assembled_model),\n                FileContentType.to_content_type(f'.{args.extension}')\n            )\n        )\n\n        plan.execute()\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.catalog/","title":"catalog","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog","title":"trestle.core.commands.author.catalog","text":"

                                                                            Author commands to generate catalog controls as markdown and assemble them back to json.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble","title":" CatalogAssemble (AuthorCommonCommand) ","text":"

                                                                            Assemble markdown files of controls into a Catalog json file.

                                                                            Source code in trestle/core/commands/author/catalog.py
                                                                            class CatalogAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into a Catalog json file.\"\"\"\n\n    name = 'catalog-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the catalog model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the input markdown file directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json Catalog'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-sp', '--set-parameters', action='store_true', help=const.HELP_SET_PARAMS)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n            return CatalogAssemble.assemble_catalog(\n                trestle_root=trestle_root,\n                md_name=args.markdown,\n                assem_cat_name=args.output,\n                parent_cat_name=args.name,\n                set_parameters_flag=args.set_parameters,\n                regenerate=args.regenerate,\n                version=args.version\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred while assembling catalog')\n\n    @staticmethod\n    def assemble_catalog(\n        trestle_root: pathlib.Path,\n        md_name: str,\n        assem_cat_name: str,\n        parent_cat_name: Optional[str],\n        set_parameters_flag: bool,\n        regenerate: bool,\n        version: Optional[str]\n    ) -> int:\n\"\"\"\n        Assemble the markdown directory into a json catalog model file.\n\n        Args:\n            trestle_root: The trestle root directory\n            md_name: The name of the directory containing the markdown control files for the ssp\n            assem_cat_name: The output name of the catalog model to be created from the assembly\n            parent_cat_name: Optional name of the parent catalog that the markdown controls will replace\n            set_parameters_flag: set the parameters and props in the control to the values in the markdown yaml header\n            regenerate: whether to regenerate the uuid's in the catalog\n            version: version for the assembled catalog\n\n        Returns:\n            0 on success, 1 otherwise\n\n        Notes:\n            If the destination catalog_name model already exists in the trestle workspace, it is overwritten.\n            If a parent catalog is not specified, the assembled catalog will be used as the parent if it exists.\n            If no parent catalog name is available, the catalog is created anew using only the markdown content.\n        \"\"\"\n        md_dir = trestle_root / md_name\n        if not md_dir.exists():\n            raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n        # assemble the markdown controls into fresh md_catalog\n        catalog_api_from_md = CatalogAPI(catalog=None)\n        try:\n            md_catalog = catalog_api_from_md.read_catalog_from_markdown(md_dir, set_parameters_flag)\n        except Exception as e:\n            raise TrestleError(f'Error reading catalog from markdown {md_dir}: {e}')\n\n        # this is None if it doesn't exist yet\n        assem_cat_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, assem_cat_name, Catalog)\n        logger.debug(f'assem_cat_path is {assem_cat_path}')\n\n        # if original cat is not specified, use the assembled cat but only if it already exists\n        if not parent_cat_name and assem_cat_path:\n            parent_cat_name = assem_cat_name\n\n        # default to JSON but allow override later if other file type found\n        new_content_type = FileContentType.JSON\n\n        # if we have parent catalog then merge the markdown controls into it\n        # the parent can be a separate catalog or the destination assembled catalog if it exists\n        # but this is the catalog that the markdown is merged into in memory\n        logger.debug(f'parent_cat_name is {parent_cat_name}')\n        if parent_cat_name:\n            parent_cat, parent_cat_path = load_validate_model_name(trestle_root, parent_cat_name, Catalog)\n            parent_cat_api = CatalogAPI(catalog=parent_cat)\n            # merge the just-read md catalog into the original json\n            parent_cat_api.merge_catalog(md_catalog, set_parameters_flag)\n            md_catalog = parent_cat_api._catalog_interface.get_catalog()\n            new_content_type = FileContentType.path_to_content_type(parent_cat_path)\n\n        if version:\n            md_catalog.metadata.version = version\n\n        # now check the destination catalog to see if the in-memory catalog matches it\n        if assem_cat_path:\n            new_content_type = FileContentType.path_to_content_type(assem_cat_path)\n            existing_cat = load_validate_model_path(trestle_root, assem_cat_path)\n            if ModelUtils.models_are_equivalent(existing_cat, md_catalog):  # type: ignore\n                logger.info('Assembled catalog is not different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n            else:\n                logger.debug('new assembled catalog is different from existing one')\n\n        if regenerate:\n            md_catalog, _, _ = ModelUtils.regenerate_uuids(md_catalog)\n            logger.debug('regenerating uuids in catalog')\n        ModelUtils.update_last_modified(md_catalog)\n\n        md_catalog.metadata.oscal_version = OSCAL_VERSION\n\n        # we still may not know the assem_cat_path but can now create it with file content type\n        assem_cat_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, assem_cat_name, Catalog, new_content_type\n        )\n\n        if assem_cat_path.parent.exists():\n            logger.info('Creating catalog from markdown and destination catalog exists, so updating.')\n            shutil.rmtree(str(assem_cat_path.parent))\n\n        assem_cat_path.parent.mkdir(parents=True, exist_ok=True)\n        md_catalog.oscal_write(assem_cat_path.parent / 'catalog.json')\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogAssemble.assemble_catalog","title":"assemble_catalog(trestle_root, md_name, assem_cat_name, parent_cat_name, set_parameters_flag, regenerate, version) staticmethod","text":"

                                                                            Assemble the markdown directory into a json catalog model file.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            The trestle root directory

                                                                            required md_name str

                                                                            The name of the directory containing the markdown control files for the ssp

                                                                            required assem_cat_name str

                                                                            The output name of the catalog model to be created from the assembly

                                                                            required parent_cat_name Optional[str]

                                                                            Optional name of the parent catalog that the markdown controls will replace

                                                                            required set_parameters_flag bool

                                                                            set the parameters and props in the control to the values in the markdown yaml header

                                                                            required regenerate bool

                                                                            whether to regenerate the uuid's in the catalog

                                                                            required version Optional[str]

                                                                            version for the assembled catalog

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success, 1 otherwise

                                                                            Notes

                                                                            If the destination catalog_name model already exists in the trestle workspace, it is overwritten. If a parent catalog is not specified, the assembled catalog will be used as the parent if it exists. If no parent catalog name is available, the catalog is created anew using only the markdown content.

                                                                            Source code in trestle/core/commands/author/catalog.py
                                                                            @staticmethod\ndef assemble_catalog(\n    trestle_root: pathlib.Path,\n    md_name: str,\n    assem_cat_name: str,\n    parent_cat_name: Optional[str],\n    set_parameters_flag: bool,\n    regenerate: bool,\n    version: Optional[str]\n) -> int:\n\"\"\"\n    Assemble the markdown directory into a json catalog model file.\n\n    Args:\n        trestle_root: The trestle root directory\n        md_name: The name of the directory containing the markdown control files for the ssp\n        assem_cat_name: The output name of the catalog model to be created from the assembly\n        parent_cat_name: Optional name of the parent catalog that the markdown controls will replace\n        set_parameters_flag: set the parameters and props in the control to the values in the markdown yaml header\n        regenerate: whether to regenerate the uuid's in the catalog\n        version: version for the assembled catalog\n\n    Returns:\n        0 on success, 1 otherwise\n\n    Notes:\n        If the destination catalog_name model already exists in the trestle workspace, it is overwritten.\n        If a parent catalog is not specified, the assembled catalog will be used as the parent if it exists.\n        If no parent catalog name is available, the catalog is created anew using only the markdown content.\n    \"\"\"\n    md_dir = trestle_root / md_name\n    if not md_dir.exists():\n        raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n    # assemble the markdown controls into fresh md_catalog\n    catalog_api_from_md = CatalogAPI(catalog=None)\n    try:\n        md_catalog = catalog_api_from_md.read_catalog_from_markdown(md_dir, set_parameters_flag)\n    except Exception as e:\n        raise TrestleError(f'Error reading catalog from markdown {md_dir}: {e}')\n\n    # this is None if it doesn't exist yet\n    assem_cat_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, assem_cat_name, Catalog)\n    logger.debug(f'assem_cat_path is {assem_cat_path}')\n\n    # if original cat is not specified, use the assembled cat but only if it already exists\n    if not parent_cat_name and assem_cat_path:\n        parent_cat_name = assem_cat_name\n\n    # default to JSON but allow override later if other file type found\n    new_content_type = FileContentType.JSON\n\n    # if we have parent catalog then merge the markdown controls into it\n    # the parent can be a separate catalog or the destination assembled catalog if it exists\n    # but this is the catalog that the markdown is merged into in memory\n    logger.debug(f'parent_cat_name is {parent_cat_name}')\n    if parent_cat_name:\n        parent_cat, parent_cat_path = load_validate_model_name(trestle_root, parent_cat_name, Catalog)\n        parent_cat_api = CatalogAPI(catalog=parent_cat)\n        # merge the just-read md catalog into the original json\n        parent_cat_api.merge_catalog(md_catalog, set_parameters_flag)\n        md_catalog = parent_cat_api._catalog_interface.get_catalog()\n        new_content_type = FileContentType.path_to_content_type(parent_cat_path)\n\n    if version:\n        md_catalog.metadata.version = version\n\n    # now check the destination catalog to see if the in-memory catalog matches it\n    if assem_cat_path:\n        new_content_type = FileContentType.path_to_content_type(assem_cat_path)\n        existing_cat = load_validate_model_path(trestle_root, assem_cat_path)\n        if ModelUtils.models_are_equivalent(existing_cat, md_catalog):  # type: ignore\n            logger.info('Assembled catalog is not different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n        else:\n            logger.debug('new assembled catalog is different from existing one')\n\n    if regenerate:\n        md_catalog, _, _ = ModelUtils.regenerate_uuids(md_catalog)\n        logger.debug('regenerating uuids in catalog')\n    ModelUtils.update_last_modified(md_catalog)\n\n    md_catalog.metadata.oscal_version = OSCAL_VERSION\n\n    # we still may not know the assem_cat_path but can now create it with file content type\n    assem_cat_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, assem_cat_name, Catalog, new_content_type\n    )\n\n    if assem_cat_path.parent.exists():\n        logger.info('Creating catalog from markdown and destination catalog exists, so updating.')\n        shutil.rmtree(str(assem_cat_path.parent))\n\n    assem_cat_path.parent.mkdir(parents=True, exist_ok=True)\n    md_catalog.oscal_write(assem_cat_path.parent / 'catalog.json')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate","title":" CatalogGenerate (AuthorCommonCommand) ","text":"

                                                                            Generate Catalog controls in markdown form from a catalog in the trestle workspace.

                                                                            Source code in trestle/core/commands/author/catalog.py
                                                                            class CatalogGenerate(AuthorCommonCommand):\n\"\"\"Generate Catalog controls in markdown form from a catalog in the trestle workspace.\"\"\"\n\n    name = 'catalog-generate'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the catalog model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument(\n            '-o', '--output', help='Name of the output generated catalog markdown folder', required=True, type=str\n        )  # noqa E501\n        self.add_argument('-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true')\n        self.add_argument('-y', '--yaml-header', help=const.HELP_YAML_PATH, required=False, type=str)\n        self.add_argument(\n            '-ohv',\n            '--overwrite-header-values',\n            help=const.HELP_OVERWRITE_HEADER_VALUES,\n            required=False,\n            action='store_true',\n            default=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = args.trestle_root\n            if not file_utils.is_directory_name_allowed(args.output):\n                raise TrestleError(f'{args.output} is not an allowed directory name')\n\n            if args.force_overwrite:\n                try:\n                    logger.info(f'Overwriting the content in {args.output} folder.')\n                    clear_folder(pathlib.Path(args.output))\n                except TrestleError as e:  # pragma: no cover\n                    raise TrestleError(f'Unable to overwrite contents in {args.output} folder: {e}')\n\n            yaml_header: Dict[str, Any] = {}\n            if args.yaml_header:\n                try:\n                    logging.debug(f'Loading yaml header file {args.yaml_header}')\n                    yaml = YAML(typ='safe')\n                    yaml_header = yaml.load(pathlib.Path(args.yaml_header).open('r'))\n                except YAMLError as e:\n                    raise TrestleError(f'YAML error loading yaml header {args.yaml_header} for ssp generation: {e}')\n\n            catalog_path = trestle_root / f'catalogs/{args.name}/catalog.json'\n\n            markdown_path = trestle_root / args.output\n\n            return self.generate_markdown(\n                trestle_root, catalog_path, markdown_path, yaml_header, args.overwrite_header_values\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when generating markdown for catalog')\n\n    def generate_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        catalog_path: pathlib.Path,\n        markdown_path: pathlib.Path,\n        yaml_header: Dict[str, Any],\n        overwrite_header_values: bool\n    ) -> int:\n\"\"\"Generate markdown for the controls in the catalog.\"\"\"\n        try:\n            catalog = load_validate_model_path(trestle_root, catalog_path)\n            context = ControlContext.generate(\n                ContextPurpose.CATALOG,\n                True,\n                trestle_root,\n                markdown_path,\n                cli_yaml_header=yaml_header,\n                overwrite_header_values=overwrite_header_values,\n                set_parameters_flag=True\n            )\n            catalog_api = CatalogAPI(catalog=catalog, context=context)\n            catalog_api.write_catalog_as_markdown()\n\n        except TrestleNotFoundError as e:\n            raise TrestleError(f'Catalog {catalog_path} not found for load: {e}')\n        except Exception as e:\n            raise TrestleError(f'Error generating markdown for controls in {catalog_path}: {e}')\n\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.catalog/#trestle.core.commands.author.catalog.CatalogGenerate.generate_markdown","title":"generate_markdown(self, trestle_root, catalog_path, markdown_path, yaml_header, overwrite_header_values)","text":"

                                                                            Generate markdown for the controls in the catalog.

                                                                            Source code in trestle/core/commands/author/catalog.py
                                                                            def generate_markdown(\n    self,\n    trestle_root: pathlib.Path,\n    catalog_path: pathlib.Path,\n    markdown_path: pathlib.Path,\n    yaml_header: Dict[str, Any],\n    overwrite_header_values: bool\n) -> int:\n\"\"\"Generate markdown for the controls in the catalog.\"\"\"\n    try:\n        catalog = load_validate_model_path(trestle_root, catalog_path)\n        context = ControlContext.generate(\n            ContextPurpose.CATALOG,\n            True,\n            trestle_root,\n            markdown_path,\n            cli_yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            set_parameters_flag=True\n        )\n        catalog_api = CatalogAPI(catalog=catalog, context=context)\n        catalog_api.write_catalog_as_markdown()\n\n    except TrestleNotFoundError as e:\n        raise TrestleError(f'Catalog {catalog_path} not found for load: {e}')\n    except Exception as e:\n        raise TrestleError(f'Error generating markdown for controls in {catalog_path}: {e}')\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.command/","title":"command","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command","title":"trestle.core.commands.author.command","text":"

                                                                            Trestle author command.

                                                                            Umbrella command for all markdown related transformations

                                                                            "},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.AuthorCmd","title":" AuthorCmd (CommandPlusDocs) ","text":"

                                                                            trestle author, a collection of commands for authoring compliance content outside of OSCAL.

                                                                            Source code in trestle/core/commands/author/command.py
                                                                            class AuthorCmd(CommandPlusDocs):\n\"\"\"trestle author, a collection of commands for authoring compliance content outside of OSCAL.\"\"\"\n\n    name = 'author'\n\n    subcommands = [\n        CatalogAssemble,\n        CatalogGenerate,\n        ComponentAssemble,\n        ComponentGenerate,\n        Docs,\n        Folders,\n        Headers,\n        JinjaCmd,\n        ProfileAssemble,\n        ProfileGenerate,\n        ProfileInherit,\n        ProfileResolve,\n        SSPAssemble,\n        SSPFilter,\n        SSPGenerate\n    ]\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.AuthorCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.command/#trestle.core.commands.author.command.AuthorCmd.subcommands","title":"subcommands","text":""},{"location":"api_reference/trestle.core.commands.author.common/","title":"common","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common","title":"trestle.core.commands.author.common","text":"

                                                                            AuthorCommonCommands - reusable utilities to increase code base abstraction for author command.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.AuthorCommonCommand","title":" AuthorCommonCommand (CommandPlusDocs) ","text":"

                                                                            Extension for the subset of commands that operate using the common mode structure.

                                                                            Source code in trestle/core/commands/author/common.py
                                                                            class AuthorCommonCommand(CommandPlusDocs):\n\"\"\"Extension for the subset of commands that operate using the common mode structure.\"\"\"\n\n    trestle_root: pathlib.Path\n\n    task_name: str\n\n    def _initialize(self, args: argparse.Namespace) -> int:\n        log.set_log_level_from_args(args)\n        # Externalize\n        self.trestle_root = args.trestle_root\n        self.task_name = args.task_name\n\n        try:\n            self.global_ = args.__getattribute__('global')\n        except AttributeError:\n            self.global_ = None\n\n        if self.task_name:\n            self.task_path = self.trestle_root / self.task_name\n            if not file_utils.is_directory_name_allowed(self.task_name):\n                logger.error(\n                    f'Task name {self.task_name} is invalid as it interferes with OSCAL and trestle reserved names.'\n                )\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n        rc = self._setup_template_dir(args)\n\n        return rc\n\n    def rel_dir(self, path: pathlib.Path) -> str:\n\"\"\"Stringify a directory relative to trestle root.\"\"\"\n        return str(path.relative_to(self.trestle_root))\n\n    def _setup_template_dir(self, args: argparse.Namespace) -> int:\n\"\"\"Set template directory and update to new format.\"\"\"\n        if not self.global_ and self.task_name is None:\n            logger.error('At least a global flag or a task name should be provided.')\n            return CmdReturnCodes.INCORRECT_ARGS.value\n        if self.global_:\n            old_template_dir = self.trestle_root / TRESTLE_CONFIG_DIR / 'author' / '__global__'\n            self._set_template_version_to_latest(args, old_template_dir)\n            self.template_dir = old_template_dir / args.template_version\n        elif self.task_name and not self.global_:\n            old_template_dir = self.trestle_root / TRESTLE_CONFIG_DIR / 'author' / self.task_name\n            self._set_template_version_to_latest(args, old_template_dir)\n            self.template_dir = old_template_dir / args.template_version\n\n        if old_template_dir.exists():\n            TemplateVersioning.update_template_folder_structure(old_template_dir)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    def _set_template_version_to_latest(self, args: argparse.Namespace, template_dir: pathlib.Path) -> None:\n\"\"\"Set template version argument to the latest version if none was given.\"\"\"\n        if not TemplateVersioning.is_valid_version(args.template_version):\n            raise TrestleError(f'Version {args.template_version} is invalid, version format should be: 0.0.1')\n        if args.template_version is None and args.mode == ARG_VALIDATE:\n            # in validate mode no version will validate instances based on header version\n            args.template_version = ''\n        if args.template_version is None:\n            args.template_version = START_TEMPLATE_VERSION\n            if template_dir.exists():\n                all_versions = TemplateVersioning.get_all_versions_for_task(template_dir)\n                if all_versions:\n                    args.template_version = max(all_versions)\n        if args.template_version == '':\n            logger.info('Instances will be validated against template version specified in their headers.')\n        else:\n            logger.info(f'Set template version to {args.template_version}.')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.AuthorCommonCommand-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.common/#trestle.core.commands.author.common.AuthorCommonCommand.rel_dir","title":"rel_dir(self, path)","text":"

                                                                            Stringify a directory relative to trestle root.

                                                                            Source code in trestle/core/commands/author/common.py
                                                                            def rel_dir(self, path: pathlib.Path) -> str:\n\"\"\"Stringify a directory relative to trestle root.\"\"\"\n    return str(path.relative_to(self.trestle_root))\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/","title":"component","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component","title":"trestle.core.commands.author.component","text":"

                                                                            Author commands to generate component definition as markdown and assemble to json after edit.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble","title":" ComponentAssemble (AuthorCommonCommand) ","text":"

                                                                            Assemble markdown files of controls into a Component json file.

                                                                            Source code in trestle/core/commands/author/component.py
                                                                            class ComponentAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into a Component json file.\"\"\"\n\n    name = 'component-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the component-definition model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the source markdown directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json component-definition (ok to overwrite original)'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            return self.assemble_component(\n                trestle_root=args.trestle_root,\n                parent_comp_name=args.name,\n                md_name=args.markdown,\n                assem_comp_name=args.output,\n                regenerate=args.regenerate,\n                version=args.version,\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Assembly of markdown to component-definition failed')\n\n    @staticmethod\n    def assemble_component(\n        trestle_root: pathlib.Path,\n        parent_comp_name: Optional[str],\n        md_name: str,\n        assem_comp_name: str,\n        regenerate: bool,\n        version: Optional[str],\n    ) -> int:\n\"\"\"\n        Assemble the markdown directory into a json component-definition model file.\n\n        Args:\n            trestle_root: The trestle root directory\n            parent_comp_name: Optional name of component-definition used to generate markdown, default = assem_comp_name\n            md_name: The name of the directory containing the markdown control files for the component\n            assem_comp_name: The name of the assembled component-definiton.  Can be same as the parent to overwrite\n            regenerate: Whether to regenerate the uuid's in the component\n            version: Optional version for the assembled component\n\n        Returns:\n            0 on success, 1 otherwise\n\n        Notes:\n            There must already be a component model and it will either be updated or a new json component created.\n            The generated markdown has the current values for parameters of controls being imported, as set by\n            the original catalog and any intermediate components.  It also shows the current SetParameters being applied\n            by this component.  That list of SetParameters can be edited by changing the assigned values and adding or\n            removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n            in the assembled component if the --set-parameters option is specified.\n        \"\"\"\n        md_dir = trestle_root / md_name\n        if not md_dir.exists():\n            raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n        if not parent_comp_name:\n            parent_comp_name = assem_comp_name\n\n        # load the comp-def that will be updated\n        parent_comp, parent_comp_path = ModelUtils.load_model_for_class(\n            trestle_root,\n            parent_comp_name,\n            comp.ComponentDefinition\n        )\n        new_content_type = FileContentType.path_to_content_type(parent_comp_path)\n\n        context = ControlContext.generate(ContextPurpose.COMPONENT, False, trestle_root, md_dir)\n\n        ComponentAssemble.assemble_comp_def_into_parent(parent_comp, md_dir, context)\n\n        if version:\n            parent_comp.metadata.version = version\n\n        assem_comp_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, assem_comp_name, comp.ComponentDefinition, new_content_type\n        )\n\n        if not version and assem_comp_path.exists():\n            _, _, existing_comp = ModelUtils.load_distributed(assem_comp_path, trestle_root)\n            # comp def will change statement uuids so need to ignore them in comparison\n            if ModelUtils.models_are_equivalent(existing_comp, parent_comp, True):  # type: ignore\n                logger.info('Assembled component definition is no different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n\n        if regenerate:\n            parent_comp, _, _ = ModelUtils.regenerate_uuids(parent_comp)\n        ModelUtils.update_last_modified(parent_comp)  # type: ignore\n\n        if assem_comp_path.parent.exists():\n            logger.info(\n                'Creating component definition from markdown and destination component definition exists, so updating.'\n            )  # noqa E501\n            shutil.rmtree(str(assem_comp_path.parent))\n\n        assem_comp_path.parent.mkdir(parents=True, exist_ok=True)\n        parent_comp.oscal_write(assem_comp_path)  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def assemble_comp_def_into_parent(\n        parent_comp: comp.ComponentDefinition, md_dir: pathlib.Path, context: ControlContext\n    ) -> None:\n\"\"\"Assemble markdown content into provided component-definition model.\"\"\"\n        # find the needed list of comps\n        sub_dirs = file_utils.iterdir_without_hidden_files(md_dir)\n        comp_names = [sub_dir.name for sub_dir in sub_dirs if sub_dir.is_dir()]\n\n        # make sure parent has list of comps to work with - possibly empty\n        if not parent_comp.components:\n            parent_comp.components = []\n\n        parent_comp.components[:] = [comp for comp in parent_comp.components if comp.title in comp_names]\n\n        # create new comps if needed\n        existing_comp_names = [component.title for component in parent_comp.components]\n        for comp_name in comp_names:\n            if comp_name not in existing_comp_names:\n                parent_comp.components.append(\n                    comp.DefinedComponent(\n                        uuid=str(uuid4()), title=comp_name, type=const.REPLACE_ME, description=const.REPLACE_ME\n                    )\n                )\n\n        for component in parent_comp.components:\n            context.comp_name = component.title\n            context.comp_def = parent_comp\n            context.component = component\n            logger.info(f'Assembling markdown for component {component.title}')\n            ComponentAssemble._update_component_with_markdown(md_dir, component, context)\n\n    @staticmethod\n    def _get_profile_title_and_href_from_dir(md_dir: pathlib.Path) -> Tuple[str, str]:\n\"\"\"Get profile title and href from yaml header of first md file found in dir that has info.\"\"\"\n        md_files = md_dir.rglob('*.md')\n        markdown_api = MarkdownAPI()\n        for md_file in md_files:\n            header, _ = markdown_api.processor.read_markdown_wo_processing(md_file)\n            prof_title = deep_get(header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.TITLE])\n            profile_href = deep_get(header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.HREF], 'unknown_href')\n            # return first one found\n            if prof_title:\n                return prof_title, profile_href\n        logger.warning(f'Cannot find profile title and href in markdown headers of directory {md_dir}')\n        return 'unknown_title', 'unknown_href'\n\n    @staticmethod\n    def _update_component_with_markdown(\n        md_dir: pathlib.Path, component: comp.DefinedComponent, context: ControlContext\n    ) -> None:\n        md_path = md_dir / component.title\n        sub_dirs = file_utils.iterdir_without_hidden_files(md_path)\n        source_dirs = [sub_dir.name for sub_dir in sub_dirs if sub_dir.is_dir()]\n        for source_dir in source_dirs:\n            profile_title, _ = ComponentAssemble._get_profile_title_and_href_from_dir(md_path / source_dir)\n            # context has defined component and comp_name\n            imp_reqs = CatalogReader.read_catalog_imp_reqs(md_path / source_dir, context)\n            # the imp_reqs need to be inserted into the correct control_implementation\n            for imp_req in imp_reqs:\n                ControlInterface.insert_imp_req_into_component(component, imp_req, profile_title, context.trestle_root)\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble.assemble_comp_def_into_parent","title":"assemble_comp_def_into_parent(parent_comp, md_dir, context) staticmethod","text":"

                                                                            Assemble markdown content into provided component-definition model.

                                                                            Source code in trestle/core/commands/author/component.py
                                                                            @staticmethod\ndef assemble_comp_def_into_parent(\n    parent_comp: comp.ComponentDefinition, md_dir: pathlib.Path, context: ControlContext\n) -> None:\n\"\"\"Assemble markdown content into provided component-definition model.\"\"\"\n    # find the needed list of comps\n    sub_dirs = file_utils.iterdir_without_hidden_files(md_dir)\n    comp_names = [sub_dir.name for sub_dir in sub_dirs if sub_dir.is_dir()]\n\n    # make sure parent has list of comps to work with - possibly empty\n    if not parent_comp.components:\n        parent_comp.components = []\n\n    parent_comp.components[:] = [comp for comp in parent_comp.components if comp.title in comp_names]\n\n    # create new comps if needed\n    existing_comp_names = [component.title for component in parent_comp.components]\n    for comp_name in comp_names:\n        if comp_name not in existing_comp_names:\n            parent_comp.components.append(\n                comp.DefinedComponent(\n                    uuid=str(uuid4()), title=comp_name, type=const.REPLACE_ME, description=const.REPLACE_ME\n                )\n            )\n\n    for component in parent_comp.components:\n        context.comp_name = component.title\n        context.comp_def = parent_comp\n        context.component = component\n        logger.info(f'Assembling markdown for component {component.title}')\n        ComponentAssemble._update_component_with_markdown(md_dir, component, context)\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentAssemble.assemble_component","title":"assemble_component(trestle_root, parent_comp_name, md_name, assem_comp_name, regenerate, version) staticmethod","text":"

                                                                            Assemble the markdown directory into a json component-definition model file.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            The trestle root directory

                                                                            required parent_comp_name Optional[str]

                                                                            Optional name of component-definition used to generate markdown, default = assem_comp_name

                                                                            required md_name str

                                                                            The name of the directory containing the markdown control files for the component

                                                                            required assem_comp_name str

                                                                            The name of the assembled component-definiton. Can be same as the parent to overwrite

                                                                            required regenerate bool

                                                                            Whether to regenerate the uuid's in the component

                                                                            required version Optional[str]

                                                                            Optional version for the assembled component

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success, 1 otherwise

                                                                            Notes

                                                                            There must already be a component model and it will either be updated or a new json component created. The generated markdown has the current values for parameters of controls being imported, as set by the original catalog and any intermediate components. It also shows the current SetParameters being applied by this component. That list of SetParameters can be edited by changing the assigned values and adding or removing SetParameters from that list. During assembly that list will be used to create the SetParameters in the assembled component if the --set-parameters option is specified.

                                                                            Source code in trestle/core/commands/author/component.py
                                                                            @staticmethod\ndef assemble_component(\n    trestle_root: pathlib.Path,\n    parent_comp_name: Optional[str],\n    md_name: str,\n    assem_comp_name: str,\n    regenerate: bool,\n    version: Optional[str],\n) -> int:\n\"\"\"\n    Assemble the markdown directory into a json component-definition model file.\n\n    Args:\n        trestle_root: The trestle root directory\n        parent_comp_name: Optional name of component-definition used to generate markdown, default = assem_comp_name\n        md_name: The name of the directory containing the markdown control files for the component\n        assem_comp_name: The name of the assembled component-definiton.  Can be same as the parent to overwrite\n        regenerate: Whether to regenerate the uuid's in the component\n        version: Optional version for the assembled component\n\n    Returns:\n        0 on success, 1 otherwise\n\n    Notes:\n        There must already be a component model and it will either be updated or a new json component created.\n        The generated markdown has the current values for parameters of controls being imported, as set by\n        the original catalog and any intermediate components.  It also shows the current SetParameters being applied\n        by this component.  That list of SetParameters can be edited by changing the assigned values and adding or\n        removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n        in the assembled component if the --set-parameters option is specified.\n    \"\"\"\n    md_dir = trestle_root / md_name\n    if not md_dir.exists():\n        raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n    if not parent_comp_name:\n        parent_comp_name = assem_comp_name\n\n    # load the comp-def that will be updated\n    parent_comp, parent_comp_path = ModelUtils.load_model_for_class(\n        trestle_root,\n        parent_comp_name,\n        comp.ComponentDefinition\n    )\n    new_content_type = FileContentType.path_to_content_type(parent_comp_path)\n\n    context = ControlContext.generate(ContextPurpose.COMPONENT, False, trestle_root, md_dir)\n\n    ComponentAssemble.assemble_comp_def_into_parent(parent_comp, md_dir, context)\n\n    if version:\n        parent_comp.metadata.version = version\n\n    assem_comp_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, assem_comp_name, comp.ComponentDefinition, new_content_type\n    )\n\n    if not version and assem_comp_path.exists():\n        _, _, existing_comp = ModelUtils.load_distributed(assem_comp_path, trestle_root)\n        # comp def will change statement uuids so need to ignore them in comparison\n        if ModelUtils.models_are_equivalent(existing_comp, parent_comp, True):  # type: ignore\n            logger.info('Assembled component definition is no different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n\n    if regenerate:\n        parent_comp, _, _ = ModelUtils.regenerate_uuids(parent_comp)\n    ModelUtils.update_last_modified(parent_comp)  # type: ignore\n\n    if assem_comp_path.parent.exists():\n        logger.info(\n            'Creating component definition from markdown and destination component definition exists, so updating.'\n        )  # noqa E501\n        shutil.rmtree(str(assem_comp_path.parent))\n\n    assem_comp_path.parent.mkdir(parents=True, exist_ok=True)\n    parent_comp.oscal_write(assem_comp_path)  # type: ignore\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate","title":" ComponentGenerate (AuthorCommonCommand) ","text":"

                                                                            Generate component in markdown form from a component in the trestle workspace.

                                                                            Source code in trestle/core/commands/author/component.py
                                                                            class ComponentGenerate(AuthorCommonCommand):\n\"\"\"Generate component in markdown form from a component in the trestle workspace.\"\"\"\n\n    name = 'component-generate'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the source component model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument(\n            '-o', '--output', help='Name of the output generated component markdown folder', required=True, type=str\n        )  # noqa E501\n        self.add_argument('-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true')\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n\n            if args.force_overwrite:\n                try:\n                    logger.info(f'Overwriting the content in {args.output} folder.')\n                    clear_folder(pathlib.Path(args.output))\n                except TrestleError as e:  # pragma: no cover\n                    raise TrestleError(f'Unable to overwrite contents in {args.output} folder: {e}')\n\n            return self.component_generate_all(args.trestle_root, args.name, args.output)\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Generation of the component markdown failed')\n\n    def component_generate_all(self, trestle_root: pathlib.Path, comp_def_name: str, markdown_dir_name: str) -> int:\n\"\"\"Generate markdown for all components in comp def.\"\"\"\n        if not file_utils.is_directory_name_allowed(markdown_dir_name):\n            raise TrestleError(f'{markdown_dir_name} is not an allowed directory name')\n        md_path = trestle_root / markdown_dir_name\n        md_path.mkdir(parents=True, exist_ok=True)\n        component_def, _ = load_validate_model_name(trestle_root, comp_def_name, comp.ComponentDefinition)\n\n        context = ControlContext.generate(ContextPurpose.COMPONENT, True, trestle_root, md_path)\n        context.prompt_responses = True\n        context.comp_def = component_def\n\n        rc = CmdReturnCodes.SUCCESS.value\n        for component in as_list(component_def.components):\n            rc = self.component_generate_by_name(context, component, md_path / component.title)\n            if rc != CmdReturnCodes.SUCCESS.value:\n                break\n        return rc\n\n    @staticmethod\n    def _get_name_from_uri(source_uri: str) -> str:\n\"\"\"Get the name from a source profile or catalog source uri.\"\"\"\n        uri_type = FetcherFactory.get_uri_type(source_uri)\n        if uri_type == FetcherFactory.UriType.TRESTLE:\n            return source_uri.split('/')[-2]\n        return ''\n\n    def component_generate_by_name(\n        self, context: ControlContext, component: comp.DefinedComponent, markdown_dir_path: pathlib.Path\n    ) -> int:\n\"\"\"Create markdown for the component using its source profiles.\"\"\"\n        logger.info(f'Generating markdown for component {component.title}')\n        context.comp_name = component.title\n        context.component = component\n        context.uri_name_map = {}\n        cat_api_dict: Dict[str, CatalogAPI] = {}\n        name_index = 1\n        for control_imp in as_list(component.control_implementations):\n            context.control_implementation = control_imp\n            source_profile_uri = control_imp.source\n            # get the resolved profile catalog for this source, generating it if not already created\n            if source_profile_uri not in cat_api_dict:\n                name = ComponentGenerate._get_name_from_uri(source_profile_uri)\n                if not name:\n                    name = f'source_{name_index:03d}'\n                    name_index += 1\n                context.uri_name_map[source_profile_uri] = name\n                resolved_catalog = ProfileResolver.get_resolved_profile_catalog(\n                    context.trestle_root, source_profile_uri, param_rep=ParameterRep.LEAVE_MOUSTACHE\n                )\n                local_catalog_api = CatalogAPI(resolved_catalog)\n                cat_api_dict[source_profile_uri] = local_catalog_api\n            else:\n                local_catalog_api = cat_api_dict[source_profile_uri]\n            # insert the profile title (from title of resolved catalog) into the yaml header so it appears in md\n            # different controls in the final catalog may have different profile titles if from different control_imps\n            context.cli_yaml_header = {}\n            context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG] = {}\n\n            profile_title = local_catalog_api._catalog_interface.get_catalog_title()\n            profile_header = {'title': profile_title, 'href': source_profile_uri}\n            context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG][const.PROFILE] = profile_header\n\n            sub_dir_name = context.uri_name_map[source_profile_uri]\n            context.md_root = markdown_dir_path / sub_dir_name\n            # write controls corresponding to this source catalog\n            # if two controlimps load the same control, the second one will merge into the first\n            # otherwise the full catalog will be written in subsets by control_imp\n            # if an imp_req has a set param also in the control_imp. the imp_req value is used for the control\n            cat_api_dict[source_profile_uri].update_context(context)\n            cat_api_dict[source_profile_uri].write_catalog_as_markdown()\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate.component_generate_all","title":"component_generate_all(self, trestle_root, comp_def_name, markdown_dir_name)","text":"

                                                                            Generate markdown for all components in comp def.

                                                                            Source code in trestle/core/commands/author/component.py
                                                                            def component_generate_all(self, trestle_root: pathlib.Path, comp_def_name: str, markdown_dir_name: str) -> int:\n\"\"\"Generate markdown for all components in comp def.\"\"\"\n    if not file_utils.is_directory_name_allowed(markdown_dir_name):\n        raise TrestleError(f'{markdown_dir_name} is not an allowed directory name')\n    md_path = trestle_root / markdown_dir_name\n    md_path.mkdir(parents=True, exist_ok=True)\n    component_def, _ = load_validate_model_name(trestle_root, comp_def_name, comp.ComponentDefinition)\n\n    context = ControlContext.generate(ContextPurpose.COMPONENT, True, trestle_root, md_path)\n    context.prompt_responses = True\n    context.comp_def = component_def\n\n    rc = CmdReturnCodes.SUCCESS.value\n    for component in as_list(component_def.components):\n        rc = self.component_generate_by_name(context, component, md_path / component.title)\n        if rc != CmdReturnCodes.SUCCESS.value:\n            break\n    return rc\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.component/#trestle.core.commands.author.component.ComponentGenerate.component_generate_by_name","title":"component_generate_by_name(self, context, component, markdown_dir_path)","text":"

                                                                            Create markdown for the component using its source profiles.

                                                                            Source code in trestle/core/commands/author/component.py
                                                                            def component_generate_by_name(\n    self, context: ControlContext, component: comp.DefinedComponent, markdown_dir_path: pathlib.Path\n) -> int:\n\"\"\"Create markdown for the component using its source profiles.\"\"\"\n    logger.info(f'Generating markdown for component {component.title}')\n    context.comp_name = component.title\n    context.component = component\n    context.uri_name_map = {}\n    cat_api_dict: Dict[str, CatalogAPI] = {}\n    name_index = 1\n    for control_imp in as_list(component.control_implementations):\n        context.control_implementation = control_imp\n        source_profile_uri = control_imp.source\n        # get the resolved profile catalog for this source, generating it if not already created\n        if source_profile_uri not in cat_api_dict:\n            name = ComponentGenerate._get_name_from_uri(source_profile_uri)\n            if not name:\n                name = f'source_{name_index:03d}'\n                name_index += 1\n            context.uri_name_map[source_profile_uri] = name\n            resolved_catalog = ProfileResolver.get_resolved_profile_catalog(\n                context.trestle_root, source_profile_uri, param_rep=ParameterRep.LEAVE_MOUSTACHE\n            )\n            local_catalog_api = CatalogAPI(resolved_catalog)\n            cat_api_dict[source_profile_uri] = local_catalog_api\n        else:\n            local_catalog_api = cat_api_dict[source_profile_uri]\n        # insert the profile title (from title of resolved catalog) into the yaml header so it appears in md\n        # different controls in the final catalog may have different profile titles if from different control_imps\n        context.cli_yaml_header = {}\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG] = {}\n\n        profile_title = local_catalog_api._catalog_interface.get_catalog_title()\n        profile_header = {'title': profile_title, 'href': source_profile_uri}\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG][const.PROFILE] = profile_header\n\n        sub_dir_name = context.uri_name_map[source_profile_uri]\n        context.md_root = markdown_dir_path / sub_dir_name\n        # write controls corresponding to this source catalog\n        # if two controlimps load the same control, the second one will merge into the first\n        # otherwise the full catalog will be written in subsets by control_imp\n        # if an imp_req has a set param also in the control_imp. the imp_req value is used for the control\n        cat_api_dict[source_profile_uri].update_context(context)\n        cat_api_dict[source_profile_uri].write_catalog_as_markdown()\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.consts/","title":"consts","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts","title":"trestle.core.commands.author.consts","text":"

                                                                            Constants associated with trestle author commands to decrease duplication.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.EXCLUDE_HELP","title":"EXCLUDE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.EXCLUDE_LONG","title":"EXCLUDE_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.EXCLUDE_SHORT","title":"EXCLUDE_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GH_HELP","title":"GH_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GH_LONG","title":"GH_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GH_SHORT","title":"GH_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GLOBAL_HELP","title":"GLOBAL_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GLOBAL_LONG","title":"GLOBAL_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.GLOBAL_SHORT","title":"GLOBAL_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HEADER_VALIDATE_HELP","title":"HEADER_VALIDATE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HOV_HELP","title":"HOV_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HOV_LONG","title":"HOV_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.HOV_SHORT","title":"HOV_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.IGNORE_HELP","title":"IGNORE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_HEADER_VALIDATE","title":"LONG_HEADER_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_IGNORE","title":"LONG_IGNORE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_README_VALIDATE","title":"LONG_README_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.LONG_TEMPLATE_VERSION","title":"LONG_TEMPLATE_VERSION","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.MODE_ARG_NAME","title":"MODE_ARG_NAME","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.MODE_CHOICES","title":"MODE_CHOICES","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.README_VALIDATE_FOLDERS_HELP","title":"README_VALIDATE_FOLDERS_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.README_VALIDATE_HELP","title":"README_VALIDATE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.RECURSE_HELP","title":"RECURSE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.RECURSE_LONG","title":"RECURSE_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.RECURSE_SHORT","title":"RECURSE_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.REFERENCE_TEMPLATES","title":"REFERENCE_TEMPLATES","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_HEADER_VALIDATE","title":"SHORT_HEADER_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_IGNORE","title":"SHORT_IGNORE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_README_VALIDATE","title":"SHORT_README_VALIDATE","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.SHORT_TEMPLATE_VERSION","title":"SHORT_TEMPLATE_VERSION","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.START_TEMPLATE_VERSION","title":"START_TEMPLATE_VERSION","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TASK_NAME_LONG","title":"TASK_NAME_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TASK_NAME_SHORT","title":"TASK_NAME_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_HEADER","title":"TEMPLATE_TYPE_HEADER","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_VALIDATE_HELP","title":"TEMPLATE_TYPE_VALIDATE_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_VALIDATE_LONG","title":"TEMPLATE_TYPE_VALIDATE_LONG","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_TYPE_VALIDATE_SHORT","title":"TEMPLATE_TYPE_VALIDATE_SHORT","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_VERSION_HEADER","title":"TEMPLATE_VERSION_HEADER","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TEMPLATE_VERSION_HELP","title":"TEMPLATE_VERSION_HELP","text":""},{"location":"api_reference/trestle.core.commands.author.consts/#trestle.core.commands.author.consts.TRESTLE_RESOURCES","title":"TRESTLE_RESOURCES","text":""},{"location":"api_reference/trestle.core.commands.author.docs/","title":"docs","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs","title":"trestle.core.commands.author.docs","text":"

                                                                            Trestle author docs sub-command.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs","title":" Docs (AuthorCommonCommand) ","text":"

                                                                            Markdown governed documents - enforcing consistent markdown across a set of files.

                                                                            Source code in trestle/core/commands/author/docs.py
                                                                            class Docs(AuthorCommonCommand):\n\"\"\"Markdown governed documents - enforcing consistent markdown across a set of files.\"\"\"\n\n    name = 'docs'\n\n    template_name = 'template.md'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            author_const.GH_SHORT, author_const.GH_LONG, help=author_const.GH_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_HEADER_VALIDATE,\n            author_const.LONG_HEADER_VALIDATE,\n            help=author_const.HEADER_VALIDATE_HELP,\n            action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_TEMPLATE_VERSION,\n            author_const.LONG_TEMPLATE_VERSION,\n            help=author_const.TEMPLATE_VERSION_HELP,\n            action='store'\n        )\n        self.add_argument(\n            author_const.HOV_SHORT, author_const.HOV_LONG, help=author_const.HOV_HELP, action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_IGNORE, author_const.LONG_IGNORE, help=author_const.IGNORE_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.RECURSE_SHORT, author_const.RECURSE_LONG, help=author_const.RECURSE_HELP, action='store_true'\n        )\n        self.add_argument(author_const.MODE_ARG_NAME, choices=author_const.MODE_CHOICES)\n        tn_help_str = '\\n'.join(\n            [\n                'The name of the the task to be governed.',\n                ''\n                'The template file is at .trestle/author/[task-name]/template.md',\n                'Note that by default this will automatically enforce the task.'\n            ]\n        )\n\n        self.add_argument(\n            author_const.TASK_NAME_SHORT, author_const.TASK_NAME_LONG, help=tn_help_str, required=True, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_README_VALIDATE,\n            author_const.LONG_README_VALIDATE,\n            help=author_const.README_VALIDATE_HELP,\n            action='store_true'\n        )\n\n        self.add_argument(\n            author_const.TEMPLATE_TYPE_VALIDATE_SHORT,\n            author_const.TEMPLATE_TYPE_VALIDATE_LONG,\n            help=author_const.TEMPLATE_TYPE_VALIDATE_HELP,\n            action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            status = 1\n            if self._initialize(args):\n                return status\n\n            if args.mode == 'create-sample':\n                status = self.create_sample()\n\n            elif args.mode == 'template-validate':\n                status = self.template_validate(\n                    args.governed_heading,\n                    args.header_validate,\n                    args.header_only_validate,\n                )\n            elif args.mode == 'setup':\n                status = self.setup_template_governed_docs(args.template_version)\n            elif args.mode == 'validate':\n                # mode is validate\n                status = self.validate(\n                    args.governed_heading,\n                    args.header_validate,\n                    args.header_only_validate,\n                    args.recurse,\n                    args.readme_validate,\n                    args.template_version,\n                    args.ignore,\n                    args.validate_template_type\n                )\n\n            return status\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle author docs')\n\n    def setup_template_governed_docs(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\n\n        Returns:\n            Unix return code.\n        \"\"\"\n        if not self.task_path.exists():\n            self.task_path.mkdir(exist_ok=True, parents=True)\n        elif self.task_path.is_file():\n            raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n        if not self.template_dir.exists():\n            self.template_dir.mkdir(exist_ok=True, parents=True)\n        elif self.template_dir.is_file():\n            raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n        logger.debug(self.template_dir)\n        if not self._validate_template_dir():\n            raise TrestleError('Aborting setup')\n        template_file = self.template_dir / self.template_name\n        if template_file.is_file():\n            return CmdReturnCodes.SUCCESS.value\n        TemplateVersioning.write_versioned_template('template.md', self.template_dir, template_file, template_version)\n        logger.info(f'Template file setup for task {self.task_name} at {self.rel_dir(template_file)}')\n        logger.info(f'Task directory is {self.rel_dir(self.task_path)}')\n        return CmdReturnCodes.SUCCESS.value\n\n    def create_sample(self) -> int:\n\"\"\"Presuming the template exists, copy into a sample markdown file with an index.\"\"\"\n        template_file = self.template_dir / self.template_name\n\n        if not self._validate_template_dir():\n            raise TrestleError('Aborting setup')\n        if not template_file.is_file():\n            raise TrestleError('No template file ... exiting.')\n\n        index = 0\n        while True:\n            candidate_task = self.task_path / f'{self.task_name}_{index:03d}.md'\n            if candidate_task.is_file():\n                index = index + 1\n            else:\n                shutil.copy(str(template_file), str(candidate_task))\n                break\n        return CmdReturnCodes.SUCCESS.value\n\n    def template_validate(self, heading: Optional[str], validate_header: bool, validate_only_header: bool) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n        template_file = self.template_dir / self.template_name\n        if not self._validate_template_dir():\n            raise TrestleError(f'Aborting setup, template directory {self.template_dir} is invalid.')\n        if not template_file.is_file():\n            raise TrestleError(f'Required template file: {self.rel_dir(template_file)} does not exist. Exiting.')\n        try:\n            md_api = MarkdownAPI()\n            validate_body = False if validate_only_header else True\n            md_api.load_validator_with_template(\n                template_file, validate_header or validate_only_header, validate_body, heading, True\n            )\n        except Exception as ex:\n            raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n        logger.info(f'TEMPLATES VALID: {self.task_name}')\n        return CmdReturnCodes.SUCCESS.value\n\n    def _validate_template_dir(self) -> bool:\n\"\"\"Template directory should only have template file.\"\"\"\n        for child in file_utils.iterdir_without_hidden_files(self.template_dir):\n            # Only allowable template file in the directory is the template directory.\n            if child.name != self.template_name and child.name.lower() != 'readme.md':\n                logger.warning(f'Unknown file: {child.name} in template directory {self.rel_dir(self.template_dir)}')\n                return False\n        return True\n\n    def _validate_dir(\n        self,\n        governed_heading: str,\n        md_dir: pathlib.Path,\n        validate_header: bool,\n        validate_only_header: bool,\n        recurse: bool,\n        readme_validate: bool,\n        template_version: Optional[str] = None,\n        ignore: Optional[str] = None,\n        validate_by_type_field: bool = False\n    ) -> int:\n\"\"\"\n        Validate md files in a directory with option to recurse.\n\n        Template version will be fetched from the instance header.\n        \"\"\"\n        # status is a linux returncode\n        status = 0\n        for item_path in md_dir.iterdir():\n            if file_utils.is_local_and_visible(item_path):\n                if item_path.is_file():\n                    if not item_path.suffix == const.MARKDOWN_FILE_EXT:\n                        logger.info(\n                            f'Unexpected file {self.rel_dir(item_path)} in folder {self.rel_dir(md_dir)}, skipping.'\n                        )\n                        continue\n                    if not readme_validate and item_path.name.lower() == 'readme.md':\n                        continue\n\n                    if ignore:\n                        p = re.compile(ignore)\n                        matched = p.match(item_path.parts[-1])\n                        if matched is not None:\n                            logger.info(f'Ignoring file {item_path} from validation.')\n                            continue\n\n                    md_api = MarkdownAPI()\n                    if template_version != '':\n                        template_file = self.template_dir / self.template_name\n                    else:\n                        instance_version = md_api.processor.fetch_value_from_header(\n                            item_path, author_const.TEMPLATE_VERSION_HEADER\n                        )\n                        if instance_version is None:\n                            instance_version = '0.0.1'\n                        versione_template_dir = TemplateVersioning.get_versioned_template_dir(\n                            self.template_dir, instance_version\n                        )\n                        # checks on naming template name out of type header if needed\n                        if validate_by_type_field:\n                            # get template name out of its type which essentially needs to be the same\n                            template_name = md_api.processor.fetch_value_from_header(\n                                item_path, author_const.TEMPLATE_TYPE_HEADER\n                            )\n                            # throw an error if template type is not present\n                            if template_name is None:\n                                logger.error(\n                                    f'INVALID: Instance file {item_path} does not have'\n                                    f' {author_const.TEMPLATE_TYPE_HEADER}'\n                                    ' field in its header and can not be validated using optional parameter validate'\n                                    ' template type field'\n                                )\n                                status = 1\n                                return status\n                            template_name = template_name + '.md'\n                            template_file = versione_template_dir / template_name\n                        else:  # continues regular flow without template type\n                            template_file = versione_template_dir / self.template_name\n                    if not template_file.is_file():\n                        raise TrestleError(\n                            f'Required template file: {self.rel_dir(template_file)} does not exist. Exiting.'\n                        )\n                    md_api.load_validator_with_template(\n                        template_file, validate_header, not validate_only_header, governed_heading\n                    )\n                    if not md_api.validate_instance(item_path):\n                        logger.info(f'INVALID: {self.rel_dir(item_path)}')\n                        status = 1\n                    else:\n                        logger.info(f'VALID: {self.rel_dir(item_path)}')\n                elif recurse:\n                    if ignore:\n                        p = re.compile(ignore)\n                        if len(list(filter(p.match, str(item_path.relative_to(md_dir)).split('/')))) > 0:\n                            logger.info(f'Ignoring directory {item_path} from validation.')\n                            continue\n                    rc = self._validate_dir(\n                        governed_heading,\n                        item_path,\n                        validate_header,\n                        validate_only_header,\n                        recurse,\n                        readme_validate,\n                        template_version,\n                        ignore,\n                        validate_by_type_field\n                    )\n                    if rc != 0:\n                        status = rc\n\n        return status\n\n    def validate(\n        self,\n        governed_heading: str,\n        validate_header: bool,\n        validate_only_header: bool,\n        recurse: bool,\n        readme_validate: bool,\n        template_version: str,\n        ignore: str,\n        validate_by_type_field: bool\n    ) -> int:\n\"\"\"\n        Validate task.\n\n        Args:\n            governed_heading: A heading for which structural enforcement (see online docs).\n            validate_header: Whether or not to validate the key structure of the yaml header to the markdown document.\n            validate_only_header: Whether to validate just the yaml header.\n            recurse: Whether to allow validated files to be in a directory tree.\n            readme_validate: Whether to validate readme files, otherwise they will be ignored.\n\n        Returns:\n            Return code to be used for the command.\n        \"\"\"\n        if not self.task_path.is_dir():\n            raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n        return self._validate_dir(\n            governed_heading,\n            self.task_path,\n            validate_header,\n            validate_only_header,\n            recurse,\n            readme_validate,\n            template_version,\n            ignore,\n            validate_by_type_field\n        )\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.template_name","title":"template_name","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.create_sample","title":"create_sample(self)","text":"

                                                                            Presuming the template exists, copy into a sample markdown file with an index.

                                                                            Source code in trestle/core/commands/author/docs.py
                                                                            def create_sample(self) -> int:\n\"\"\"Presuming the template exists, copy into a sample markdown file with an index.\"\"\"\n    template_file = self.template_dir / self.template_name\n\n    if not self._validate_template_dir():\n        raise TrestleError('Aborting setup')\n    if not template_file.is_file():\n        raise TrestleError('No template file ... exiting.')\n\n    index = 0\n    while True:\n        candidate_task = self.task_path / f'{self.task_name}_{index:03d}.md'\n        if candidate_task.is_file():\n            index = index + 1\n        else:\n            shutil.copy(str(template_file), str(candidate_task))\n            break\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.setup_template_governed_docs","title":"setup_template_governed_docs(self, template_version)","text":"

                                                                            Create structure to allow markdown template enforcement.

                                                                            Returns:

                                                                            Type Description int

                                                                            Unix return code.

                                                                            Source code in trestle/core/commands/author/docs.py
                                                                            def setup_template_governed_docs(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\n\n    Returns:\n        Unix return code.\n    \"\"\"\n    if not self.task_path.exists():\n        self.task_path.mkdir(exist_ok=True, parents=True)\n    elif self.task_path.is_file():\n        raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n    if not self.template_dir.exists():\n        self.template_dir.mkdir(exist_ok=True, parents=True)\n    elif self.template_dir.is_file():\n        raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n    logger.debug(self.template_dir)\n    if not self._validate_template_dir():\n        raise TrestleError('Aborting setup')\n    template_file = self.template_dir / self.template_name\n    if template_file.is_file():\n        return CmdReturnCodes.SUCCESS.value\n    TemplateVersioning.write_versioned_template('template.md', self.template_dir, template_file, template_version)\n    logger.info(f'Template file setup for task {self.task_name} at {self.rel_dir(template_file)}')\n    logger.info(f'Task directory is {self.rel_dir(self.task_path)}')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.template_validate","title":"template_validate(self, heading, validate_header, validate_only_header)","text":"

                                                                            Validate that the template is acceptable markdown.

                                                                            Source code in trestle/core/commands/author/docs.py
                                                                            def template_validate(self, heading: Optional[str], validate_header: bool, validate_only_header: bool) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n    template_file = self.template_dir / self.template_name\n    if not self._validate_template_dir():\n        raise TrestleError(f'Aborting setup, template directory {self.template_dir} is invalid.')\n    if not template_file.is_file():\n        raise TrestleError(f'Required template file: {self.rel_dir(template_file)} does not exist. Exiting.')\n    try:\n        md_api = MarkdownAPI()\n        validate_body = False if validate_only_header else True\n        md_api.load_validator_with_template(\n            template_file, validate_header or validate_only_header, validate_body, heading, True\n        )\n    except Exception as ex:\n        raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n    logger.info(f'TEMPLATES VALID: {self.task_name}')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.docs/#trestle.core.commands.author.docs.Docs.validate","title":"validate(self, governed_heading, validate_header, validate_only_header, recurse, readme_validate, template_version, ignore, validate_by_type_field)","text":"

                                                                            Validate task.

                                                                            Parameters:

                                                                            Name Type Description Default governed_heading str

                                                                            A heading for which structural enforcement (see online docs).

                                                                            required validate_header bool

                                                                            Whether or not to validate the key structure of the yaml header to the markdown document.

                                                                            required validate_only_header bool

                                                                            Whether to validate just the yaml header.

                                                                            required recurse bool

                                                                            Whether to allow validated files to be in a directory tree.

                                                                            required readme_validate bool

                                                                            Whether to validate readme files, otherwise they will be ignored.

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            Return code to be used for the command.

                                                                            Source code in trestle/core/commands/author/docs.py
                                                                            def validate(\n    self,\n    governed_heading: str,\n    validate_header: bool,\n    validate_only_header: bool,\n    recurse: bool,\n    readme_validate: bool,\n    template_version: str,\n    ignore: str,\n    validate_by_type_field: bool\n) -> int:\n\"\"\"\n    Validate task.\n\n    Args:\n        governed_heading: A heading for which structural enforcement (see online docs).\n        validate_header: Whether or not to validate the key structure of the yaml header to the markdown document.\n        validate_only_header: Whether to validate just the yaml header.\n        recurse: Whether to allow validated files to be in a directory tree.\n        readme_validate: Whether to validate readme files, otherwise they will be ignored.\n\n    Returns:\n        Return code to be used for the command.\n    \"\"\"\n    if not self.task_path.is_dir():\n        raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n    return self._validate_dir(\n        governed_heading,\n        self.task_path,\n        validate_header,\n        validate_only_header,\n        recurse,\n        readme_validate,\n        template_version,\n        ignore,\n        validate_by_type_field\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.folders/","title":"folders","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders","title":"trestle.core.commands.author.folders","text":"

                                                                            Trestle author docs sub-command.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders","title":" Folders (AuthorCommonCommand) ","text":"

                                                                            Markdown governed folders - enforcing consistent files and templates across directories.

                                                                            Source code in trestle/core/commands/author/folders.py
                                                                            class Folders(AuthorCommonCommand):\n\"\"\"Markdown governed folders - enforcing consistent files and templates across directories.\"\"\"\n\n    name = 'folders'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            author_const.GH_SHORT, author_const.GH_LONG, help=author_const.GH_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_HEADER_VALIDATE,\n            author_const.LONG_HEADER_VALIDATE,\n            help=author_const.HEADER_VALIDATE_HELP,\n            action='store_true'\n        )\n        self.add_argument(\n            author_const.HOV_SHORT, author_const.HOV_LONG, help=author_const.HOV_HELP, action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_TEMPLATE_VERSION,\n            author_const.LONG_TEMPLATE_VERSION,\n            help=author_const.TEMPLATE_VERSION_HELP,\n            action='store'\n        )\n        self.add_argument(\n            author_const.SHORT_IGNORE, author_const.LONG_IGNORE, help=author_const.IGNORE_HELP, default=None, type=str\n        )\n        self.add_argument(author_const.MODE_ARG_NAME, choices=author_const.MODE_CHOICES)\n        tn_help_str = '\\n'.join(\n            [\n                'The name of the the task to be governed.',\n                '',\n                'The template files are at .trestle/author/[task-name],',\n                'where the directory tree established and the markdown files within that directory'\n                + 'tree are enforced.'\n            ]\n        )\n\n        self.add_argument(\n            author_const.TASK_NAME_SHORT, author_const.TASK_NAME_LONG, help=tn_help_str, required=True, type=str\n        )\n        self.add_argument(\n            author_const.SHORT_README_VALIDATE,\n            author_const.LONG_README_VALIDATE,\n            help=author_const.README_VALIDATE_FOLDERS_HELP,\n            action='store_true'\n        )\n\n        self.add_argument(\n            author_const.TEMPLATE_TYPE_VALIDATE_SHORT,\n            author_const.TEMPLATE_TYPE_VALIDATE_LONG,\n            help=author_const.TEMPLATE_TYPE_VALIDATE_HELP,\n            action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            if self._initialize(args):\n                raise TrestleError(f'Error when initializing trestle folders command with args: {args}')\n            if args.mode == 'create-sample':\n                status = self.create_sample()\n\n            elif args.mode == 'template-validate':\n                status = self.template_validate(\n                    args.header_validate, args.header_only_validate, args.governed_heading, args.readme_validate\n                )\n            elif args.mode == 'setup':\n                status = self.setup_template(args.template_version)\n            elif args.mode == 'validate':\n                # mode is validate\n                status = self.validate(\n                    args.header_validate,\n                    args.header_only_validate,\n                    args.governed_heading,\n                    args.readme_validate,\n                    args.template_version,\n                    args.ignore,\n                    args.validate_template_type\n                )\n            else:\n                raise TrestleIncorrectArgsError(f'Unsupported mode: {args.mode} for folders command.')\n\n            return status\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle author folders')\n\n    def setup_template(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\"\"\"\n        if not self.task_path.exists():\n            self.task_path.mkdir(exist_ok=True, parents=True)\n        elif self.task_path.is_file():\n            raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n        if not self.template_dir.exists():\n            self.template_dir.mkdir(exist_ok=True, parents=True)\n        elif self.template_dir.is_file():\n            raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n\n        template_file_a_md = self.template_dir / 'a_template.md'\n        template_file_another_md = self.template_dir / 'another_template.md'\n        template_file_drawio = self.template_dir / 'architecture.drawio'\n        TemplateVersioning.write_versioned_template(\n            'template.md', self.template_dir, template_file_a_md, template_version\n        )\n        TemplateVersioning.write_versioned_template(\n            'template.md', self.template_dir, template_file_another_md, template_version\n        )\n        TemplateVersioning.write_versioned_template(\n            'template.drawio', self.template_dir, template_file_drawio, template_version\n        )\n\n        return CmdReturnCodes.SUCCESS.value\n\n    def template_validate(\n        self, validate_header: bool, validate_only_header: bool, heading: str, readme_validate: bool\n    ) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n        if not self.template_dir.is_dir():\n            raise TrestleError(\n                f'Template directory {self.rel_dir(self.template_dir)} for task {self.task_name} does not exist.'\n            )\n        # get list of files:\n        template_files = self.template_dir.rglob('*')\n\n        for template_file in template_files:\n            try:\n                if not file_utils.is_local_and_visible(template_file):\n                    continue\n                elif template_file.is_dir():\n                    continue\n                elif template_file.suffix.lower() == const.MARKDOWN_FILE_EXT:\n                    if not readme_validate and template_file.name == 'readme.md':\n                        raise TrestleError('Template directory contains a readme.md file and readme validation is off.')\n\n                    md_api = MarkdownAPI()\n                    md_api.load_validator_with_template(\n                        template_file, validate_header, not validate_only_header, heading\n                    )\n                elif template_file.suffix.lower().lstrip('.') == 'drawio':\n                    _ = draw_io.DrawIOMetadataValidator(template_file)\n                else:\n                    logger.info(\n                        f'File: {self.rel_dir(template_file)} within the template directory was ignored'\n                        + ' as it is not markdown.'\n                    )\n            except Exception as ex:\n                raise TrestleError(\n                    f'Template file {self.rel_dir(template_file)} for task {self.task_name}'\n                    + f' failed to validate due to {ex}'\n                )\n        logger.info(f'TEMPLATES VALID: {self.task_name}.')\n        return CmdReturnCodes.SUCCESS.value\n\n    def _measure_template_folder(\n        self,\n        instance_dir: pathlib.Path,\n        validate_header: bool,\n        validate_only_header: bool,\n        governed_heading: str,\n        readme_validate: bool,\n        template_version: str,\n        ignore: str,\n        validate_by_type_field: bool,\n    ) -> bool:\n\"\"\"\n        Validate instances against templates.\n\n        Validation will succeed if:\n            1. All template files from the specified version are present in the task\n            2. All of the instances are valid\n        \"\"\"\n        all_versioned_templates: Dict[str, Any] = {}\n        instance_version = template_version\n        instance_file_names: List[pathlib.Path] = []\n        # Fetch all instances versions and build dictionary of required template files\n        for instance_file in instance_dir.iterdir():\n            if not file_utils.is_local_and_visible(instance_file):\n                continue\n            if not instance_file.is_file():\n                continue\n            if instance_file.name.lower() == 'readme.md' and not readme_validate:\n                continue\n            if ignore:\n                p = re.compile(ignore)\n                matched = p.match(instance_file.parts[-1])\n                if matched is not None:\n                    logger.info(f'Ignoring file {instance_file} from validation.')\n                    continue\n            instance_file_name = instance_file.relative_to(instance_dir)\n            instance_file_names.append(instance_file_name)\n            if instance_file.suffix == const.MARKDOWN_FILE_EXT:\n                md_api = MarkdownAPI()\n                versioned_template_dir = None\n                # checks on naming template name out of type header if needed\n                if validate_by_type_field:\n                    template_name = md_api.processor.fetch_value_from_header(\n                        instance_file, author_const.TEMPLATE_TYPE_HEADER\n                    )\n                    if template_name is None:\n                        logger.warning(\n                            f'INVALID: Instance file {instance_file_name} does not have'\n                            f' {author_const.TEMPLATE_TYPE_HEADER}'\n                            ' field in its header and can not be validated using optional parameter validate'\n                            ' template type field'\n                        )\n                        return False\n                    template_name = template_name + '.md'\n                else:\n                    template_name = instance_file_name\n                if template_version != '':\n                    template_file = self.template_dir / template_name\n                    versioned_template_dir = self.template_dir\n                else:\n                    instance_version = md_api.processor.fetch_value_from_header(\n                        instance_file, author_const.TEMPLATE_VERSION_HEADER\n                    )\n                    if instance_version is None:\n                        instance_version = '0.0.1'  # backward compatibility\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n                    template_file = versioned_template_dir / template_name\n\n                # Check if instance is in the available templates,\n                # additional files are allowed but should not be validated.\n                templates = self._get_templates(versioned_template_dir, readme_validate)\n                is_template_present = False\n                template_type_is_valid = False\n                for template in templates:\n                    # checks if valdation needs to check on x-trestle-template-type field on header\n                    if validate_by_type_field:\n                        instance_template_type = md_api.processor.fetch_value_from_header(\n                            instance_file, author_const.TEMPLATE_TYPE_HEADER\n                        )\n                        if template.stem == instance_template_type:\n                            is_template_present = True\n                            template_type_is_valid = True\n                            break\n                    # validation through template type field is not needed and performs validation\n                    # through file name flow as usual\n                    else:\n                        if template.name == str(instance_file_name):\n                            is_template_present = True\n                            break\n\n                if not is_template_present:\n                    logger.info(\n                        f'INFO: File{instance_file} will not be validated '\n                        f'as its name does not match any template file.'\n                    )\n                    continue\n\n                if instance_version not in all_versioned_templates.keys():\n                    all_versioned_templates[instance_version] = dict.fromkeys(\n                        [t.relative_to(versioned_template_dir) for t in templates], False\n                    )\n\n                if instance_file_name in all_versioned_templates[instance_version] or template_type_is_valid:\n                    # validate\n                    md_api.load_validator_with_template(\n                        template_file, validate_header, not validate_only_header, governed_heading\n                    )\n                    status = md_api.validate_instance(instance_file)\n                    if not status:\n                        logger.warning(\n                            f'INVALID: Markdown file {instance_file} failed validation against' + f' {template_file}'\n                        )\n                        return False\n                    else:\n                        logger.info(f'VALID: {instance_file}')\n                    # mark template as present\n                    if template_type_is_valid:\n                        template_file_name = [\n                            temp.relative_to(versioned_template_dir) for temp in templates if temp.name == template_name\n                        ]\n                        all_versioned_templates[instance_version][template_file_name[0]] = True\n                    else:\n                        all_versioned_templates[instance_version][instance_file_name] = True\n\n            elif instance_file.suffix == const.DRAWIO_FILE_EXT:\n                drawio = draw_io.DrawIO(instance_file)\n                metadata = drawio.get_metadata()[0]\n                versioned_template_dir = None\n                if template_version != '':\n                    template_file = self.template_dir / instance_file_name\n                    versioned_template_dir = self.template_dir\n                else:\n                    if author_const.TEMPLATE_VERSION_HEADER in metadata.keys():\n                        instance_version = metadata[author_const.TEMPLATE_VERSION_HEADER]\n                    else:\n                        instance_version = '0.0.1'  # backward compatibility\n\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n                    template_file = versioned_template_dir / instance_file_name\n\n                if instance_version not in all_versioned_templates.keys():\n                    templates = self._get_templates(versioned_template_dir, readme_validate)\n\n                    all_versioned_templates[instance_version] = dict.fromkeys(\n                        [t.relative_to(versioned_template_dir) for t in templates], False\n                    )\n\n                if instance_file_name in all_versioned_templates[instance_version]:\n                    # validate\n                    drawio_validator = draw_io.DrawIOMetadataValidator(template_file)\n                    status = drawio_validator.validate(instance_file)\n                    if not status:\n                        logger.warning(\n                            f'INVALID: Drawio file {instance_file} failed validation against' + f' {template_file}'\n                        )\n                        return False\n                    else:\n                        logger.info(f'VALID: {instance_file}')\n                    # mark template as present\n                    all_versioned_templates[instance_version][instance_file_name] = True\n\n            else:\n                logger.debug(f'Unsupported extension of the instance file: {instance_file}, will not be validated.')\n\n        # Check that all template files are present\n        for version in all_versioned_templates.keys():\n            for template in all_versioned_templates[version]:\n                if not all_versioned_templates[version][template]:\n                    logger.warning(\n                        f'Required template file {template} does not exist in measured instance' + f'{instance_dir}'\n                    )\n                    return False\n\n        return True\n\n    def _get_templates(self, versioned_template_dir: pathlib.Path, readme_validate: bool) -> List[pathlib.Path]:\n\"\"\"Get templates for the given version.\"\"\"\n        templates = list(\n            filter(\n                lambda p: file_utils.is_local_and_visible(p) and p.is_file()\n                and  # noqa: W504 - conflicting lint and formatting\n                (p.suffix == const.MARKDOWN_FILE_EXT or p.suffix == const.DRAWIO_FILE_EXT),\n                versioned_template_dir.iterdir()\n            )\n        )\n        if not readme_validate:\n            templates = list(filter(lambda p: p.name.lower() != 'readme.md', templates))\n\n        return templates\n\n    def create_sample(self) -> int:\n\"\"\"\n        Create a sample folder within the task and populate with template content.\n\n        Returns:\n            Unix return code for running sample as a command.\n        \"\"\"\n        ii = 0\n        while True:\n            sample_path = self.task_path / f'sample_folder_{ii}'\n            if sample_path.exists():\n                ii = ii + 1\n                continue\n            shutil.copytree(str(self.template_dir), str(sample_path))\n            return CmdReturnCodes.SUCCESS.value\n\n    def validate(\n        self,\n        validate_header: bool,\n        validate_only_header: bool,\n        governed_heading: str,\n        readme_validate: bool,\n        template_version: str,\n        ignore: str,\n        validate_by_type_field: bool,\n    ) -> int:\n\"\"\"Validate task.\"\"\"\n        if not self.task_path.is_dir():\n            raise TrestleError(f'Task directory {self.task_path} does not exist. Exiting validate.')\n\n        for task_instance in self.task_path.iterdir():\n            if task_instance.is_dir():\n                if file_utils.is_symlink(task_instance):\n                    continue\n                result = self._measure_template_folder(\n                    task_instance,\n                    validate_header,\n                    validate_only_header,\n                    governed_heading,\n                    readme_validate,\n                    template_version,\n                    ignore,\n                    validate_by_type_field\n                )\n                if not result:\n                    raise TrestleError(\n                        'Governed-folder validation failed for task'\n                        + f'{self.task_name} on directory {self.rel_dir(task_instance)}'\n                    )\n            else:\n                logger.info(\n                    f'Unexpected file {self.rel_dir(task_instance)} identified in {self.task_name}'\n                    + ' directory, ignoring.'\n                )\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.create_sample","title":"create_sample(self)","text":"

                                                                            Create a sample folder within the task and populate with template content.

                                                                            Returns:

                                                                            Type Description int

                                                                            Unix return code for running sample as a command.

                                                                            Source code in trestle/core/commands/author/folders.py
                                                                            def create_sample(self) -> int:\n\"\"\"\n    Create a sample folder within the task and populate with template content.\n\n    Returns:\n        Unix return code for running sample as a command.\n    \"\"\"\n    ii = 0\n    while True:\n        sample_path = self.task_path / f'sample_folder_{ii}'\n        if sample_path.exists():\n            ii = ii + 1\n            continue\n        shutil.copytree(str(self.template_dir), str(sample_path))\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.setup_template","title":"setup_template(self, template_version)","text":"

                                                                            Create structure to allow markdown template enforcement.

                                                                            Source code in trestle/core/commands/author/folders.py
                                                                            def setup_template(self, template_version: str) -> int:\n\"\"\"Create structure to allow markdown template enforcement.\"\"\"\n    if not self.task_path.exists():\n        self.task_path.mkdir(exist_ok=True, parents=True)\n    elif self.task_path.is_file():\n        raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n    if not self.template_dir.exists():\n        self.template_dir.mkdir(exist_ok=True, parents=True)\n    elif self.template_dir.is_file():\n        raise TrestleError(f'Template path: {self.rel_dir(self.template_dir)} is a file not a directory.')\n\n    template_file_a_md = self.template_dir / 'a_template.md'\n    template_file_another_md = self.template_dir / 'another_template.md'\n    template_file_drawio = self.template_dir / 'architecture.drawio'\n    TemplateVersioning.write_versioned_template(\n        'template.md', self.template_dir, template_file_a_md, template_version\n    )\n    TemplateVersioning.write_versioned_template(\n        'template.md', self.template_dir, template_file_another_md, template_version\n    )\n    TemplateVersioning.write_versioned_template(\n        'template.drawio', self.template_dir, template_file_drawio, template_version\n    )\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.template_validate","title":"template_validate(self, validate_header, validate_only_header, heading, readme_validate)","text":"

                                                                            Validate that the template is acceptable markdown.

                                                                            Source code in trestle/core/commands/author/folders.py
                                                                            def template_validate(\n    self, validate_header: bool, validate_only_header: bool, heading: str, readme_validate: bool\n) -> int:\n\"\"\"Validate that the template is acceptable markdown.\"\"\"\n    if not self.template_dir.is_dir():\n        raise TrestleError(\n            f'Template directory {self.rel_dir(self.template_dir)} for task {self.task_name} does not exist.'\n        )\n    # get list of files:\n    template_files = self.template_dir.rglob('*')\n\n    for template_file in template_files:\n        try:\n            if not file_utils.is_local_and_visible(template_file):\n                continue\n            elif template_file.is_dir():\n                continue\n            elif template_file.suffix.lower() == const.MARKDOWN_FILE_EXT:\n                if not readme_validate and template_file.name == 'readme.md':\n                    raise TrestleError('Template directory contains a readme.md file and readme validation is off.')\n\n                md_api = MarkdownAPI()\n                md_api.load_validator_with_template(\n                    template_file, validate_header, not validate_only_header, heading\n                )\n            elif template_file.suffix.lower().lstrip('.') == 'drawio':\n                _ = draw_io.DrawIOMetadataValidator(template_file)\n            else:\n                logger.info(\n                    f'File: {self.rel_dir(template_file)} within the template directory was ignored'\n                    + ' as it is not markdown.'\n                )\n        except Exception as ex:\n            raise TrestleError(\n                f'Template file {self.rel_dir(template_file)} for task {self.task_name}'\n                + f' failed to validate due to {ex}'\n            )\n    logger.info(f'TEMPLATES VALID: {self.task_name}.')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.folders/#trestle.core.commands.author.folders.Folders.validate","title":"validate(self, validate_header, validate_only_header, governed_heading, readme_validate, template_version, ignore, validate_by_type_field)","text":"

                                                                            Validate task.

                                                                            Source code in trestle/core/commands/author/folders.py
                                                                            def validate(\n    self,\n    validate_header: bool,\n    validate_only_header: bool,\n    governed_heading: str,\n    readme_validate: bool,\n    template_version: str,\n    ignore: str,\n    validate_by_type_field: bool,\n) -> int:\n\"\"\"Validate task.\"\"\"\n    if not self.task_path.is_dir():\n        raise TrestleError(f'Task directory {self.task_path} does not exist. Exiting validate.')\n\n    for task_instance in self.task_path.iterdir():\n        if task_instance.is_dir():\n            if file_utils.is_symlink(task_instance):\n                continue\n            result = self._measure_template_folder(\n                task_instance,\n                validate_header,\n                validate_only_header,\n                governed_heading,\n                readme_validate,\n                template_version,\n                ignore,\n                validate_by_type_field\n            )\n            if not result:\n                raise TrestleError(\n                    'Governed-folder validation failed for task'\n                    + f'{self.task_name} on directory {self.rel_dir(task_instance)}'\n                )\n        else:\n            logger.info(\n                f'Unexpected file {self.rel_dir(task_instance)} identified in {self.task_name}'\n                + ' directory, ignoring.'\n            )\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.headers/","title":"headers","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers","title":"trestle.core.commands.author.headers","text":"

                                                                            Trestle author headers command.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers","title":" Headers (AuthorCommonCommand) ","text":"

                                                                            Enforce header / metadata across file types supported by author (markdown and drawio).

                                                                            Source code in trestle/core/commands/author/headers.py
                                                                            class Headers(AuthorCommonCommand):\n\"\"\"Enforce header / metadata across file types supported by author (markdown and drawio).\"\"\"\n\n    name = 'headers'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            author_const.RECURSE_SHORT, author_const.RECURSE_LONG, help=author_const.RECURSE_HELP, action='store_true'\n        )\n        self.add_argument(author_const.MODE_ARG_NAME, choices=author_const.MODE_CHOICES)\n        tn_help_str = '\\n'.join(\n            [\n                'The name of the the task to be governed.',\n                '',\n                'The template files for header metadata governance are located at .trestle/author/[task name]',\n                'Currently supported types are:',\n                'Markdown: .trestle/author/[task name]/template.md',\n                'Drawio: .trestle/author/[task name]/template.drawio',\n                '',\n                'Note that by default this will automatically enforce the task.'\n            ]\n        )\n        self.add_argument(\n            author_const.TASK_NAME_SHORT, author_const.TASK_NAME_LONG, help=tn_help_str, type=str, default=None\n        )\n        self.add_argument(\n            author_const.SHORT_README_VALIDATE,\n            author_const.LONG_README_VALIDATE,\n            help=author_const.README_VALIDATE_HELP,\n            action='store_true'\n        )\n        self.add_argument(\n            author_const.SHORT_TEMPLATE_VERSION,\n            author_const.LONG_TEMPLATE_VERSION,\n            help=author_const.TEMPLATE_VERSION_HELP,\n            action='store'\n        )\n        self.add_argument(\n            author_const.SHORT_IGNORE, author_const.LONG_IGNORE, help=author_const.IGNORE_HELP, default=None, type=str\n        )\n        self.add_argument(\n            author_const.GLOBAL_SHORT, author_const.GLOBAL_LONG, help=author_const.GLOBAL_HELP, action='store_true'\n        )\n        self.add_argument(\n            author_const.EXCLUDE_SHORT,\n            author_const.EXCLUDE_LONG,\n            help=author_const.EXCLUDE_HELP,\n            type=pathlib.Path,\n            nargs='*',\n            default=None\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            status = 1\n            if self._initialize(args):\n                return status\n            # Handle conditional requirement of args.task_name\n            # global is special so we need to use get attribute.\n            if not self.global_ and not self.task_name:\n                logger.warning('Task name (-tn) argument is required when global is not specified')\n                return status\n\n            if args.exclude:\n                logger.warning('--exclude or -e is deprecated, use --ignore instead.')\n\n            if args.mode == 'create-sample':\n                status = self.create_sample()\n\n            elif args.mode == 'template-validate':\n                status = self.template_validate()\n            elif args.mode == 'setup':\n                status = self.setup(args.template_version)\n            elif args.mode == 'validate':\n                exclusions = []\n                if args.exclude:\n                    exclusions = args.exclude\n                # mode is validate\n                status = self.validate(\n                    args.recurse, args.readme_validate, exclusions, args.template_version, args.ignore\n                )\n            return status\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle author headers')\n\n    def create_sample(self) -> int:\n\"\"\"Create sample object, this always defaults to markdown.\"\"\"\n        logger.info('Header only validation does not support sample creation.')\n        logger.info('Exiting')\n        return CmdReturnCodes.SUCCESS.value\n\n    def setup(self, template_version: str) -> int:\n\"\"\"Create template directory and templates.\"\"\"\n        # Step 1 - validation\n\n        if self.task_name and not self.task_path.exists():\n            self.task_path.mkdir(exist_ok=True, parents=True)\n        elif self.task_name and self.task_path.is_file():\n            raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n\n        if not self.template_dir.exists():\n            self.template_dir.mkdir(exist_ok=True, parents=True)\n        logger.info(f'Populating template files to {self.rel_dir(self.template_dir)}')\n        for template in author_const.REFERENCE_TEMPLATES.values():\n            destination_path = self.template_dir / template\n            TemplateVersioning.write_versioned_template(template, self.template_dir, destination_path, template_version)\n\n            logger.info(f'Template directory populated {self.rel_dir(destination_path)}')\n        return CmdReturnCodes.SUCCESS.value\n\n    def template_validate(self) -> int:\n\"\"\"Validate the integrity of the template files.\"\"\"\n        logger.info('Checking template file integrity')\n        for template_file in self.template_dir.iterdir():\n            if (template_file.name not in author_const.REFERENCE_TEMPLATES.values()\n                    and template_file.name.lower() != 'readme.md'):\n                raise TrestleError(f'Unexpected template file {self.rel_dir(template_file)}')\n\n            if template_file.suffix == const.MARKDOWN_FILE_EXT:\n                try:\n                    md_api = MarkdownAPI()\n                    md_api.load_validator_with_template(template_file, True, False)\n                except Exception as ex:\n                    raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n            elif template_file.suffix == const.DRAWIO_FILE_EXT:\n                try:\n                    _ = DrawIOMetadataValidator(template_file)\n                except Exception as ex:\n                    raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n        logger.info('Templates validated')\n        return CmdReturnCodes.SUCCESS.value\n\n    def _validate_dir(\n        self,\n        candidate_dir: pathlib.Path,\n        recurse: bool,\n        readme_validate: bool,\n        relative_exclusions: List[pathlib.Path],\n        template_version: str,\n        ignore: str\n    ) -> bool:\n\"\"\"Validate a directory within the trestle workspace.\"\"\"\n        all_versioned_templates: Dict[str, Any] = {}\n        instance_version = template_version\n        instance_file_names: List[pathlib.Path] = []\n        # Fetch all instances versions and build dictionary of required template files\n        instances = list(candidate_dir.iterdir())\n        if recurse:\n            instances = candidate_dir.rglob('*')\n            if ignore:\n                p = re.compile(ignore)\n                instances = list(\n                    filter(\n                        lambda f: len(list(filter(p.match, str(f.relative_to(candidate_dir)).split('/')))) == 0,\n                        instances\n                    )\n                )\n        for instance_file in instances:\n            if not file_utils.is_local_and_visible(instance_file):\n                continue\n            if instance_file.name.lower() == 'readme.md' and not readme_validate:\n                continue\n            if instance_file.is_dir() and not recurse:\n                continue\n            if any(str(ex) in str(instance_file) for ex in relative_exclusions):\n                continue\n            if ignore:\n                p = re.compile(ignore)\n                matched = p.match(instance_file.parts[-1])\n                if matched is not None:\n                    logger.info(f'Ignoring file {instance_file} from validation.')\n                    continue\n            instance_file_name = instance_file.relative_to(candidate_dir)\n            instance_file_names.append(instance_file_name)\n            if instance_file.suffix == const.MARKDOWN_FILE_EXT:\n                md_api = MarkdownAPI()\n                versioned_template_dir = None\n                if template_version != '':\n                    versioned_template_dir = self.template_dir\n                else:\n                    instance_version = md_api.processor.fetch_value_from_header(\n                        instance_file, author_const.TEMPLATE_VERSION_HEADER\n                    )\n                    if instance_version is None:\n                        instance_version = '0.0.1'  # backward compatibility\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n\n                if instance_version not in all_versioned_templates.keys():\n                    templates = list(\n                        filter(lambda p: file_utils.is_local_and_visible(p), versioned_template_dir.iterdir())\n                    )\n                    if not readme_validate:\n                        templates = list(filter(lambda p: p.name.lower() != 'readme.md', templates))\n                    self._update_templates(all_versioned_templates, templates, instance_version)\n\n                # validate\n                md_api.load_validator_with_template(all_versioned_templates[instance_version]['md'], True, False)\n                status = md_api.validate_instance(instance_file)\n                if not status:\n                    logger.info(f'INVALID: {self.rel_dir(instance_file)}')\n                    return False\n                else:\n                    logger.info(f'VALID: {self.rel_dir(instance_file)}')\n\n            elif instance_file.suffix == const.DRAWIO_FILE_EXT:\n                drawio = DrawIO(instance_file)\n                metadata = drawio.get_metadata()[0]\n\n                versioned_template_dir = None\n                if template_version != '':\n                    versioned_template_dir = self.template_dir\n                else:\n                    if author_const.TEMPLATE_VERSION_HEADER in metadata.keys():\n                        instance_version = metadata[author_const.TEMPLATE_VERSION_HEADER]\n                    else:\n                        instance_version = '0.0.1'  # backward compatibility\n\n                    versioned_template_dir = TemplateVersioning.get_versioned_template_dir(\n                        self.template_dir, instance_version\n                    )\n\n                if instance_version not in all_versioned_templates.keys():\n                    templates = list(\n                        filter(lambda p: file_utils.is_local_and_visible(p), versioned_template_dir.iterdir())\n                    )\n                    if not readme_validate:\n                        templates = list(filter(lambda p: p.name.lower() != 'readme.md', templates))\n                    self._update_templates(all_versioned_templates, templates, instance_version)\n\n                # validate\n                drawio_validator = DrawIOMetadataValidator(all_versioned_templates[instance_version]['drawio'])\n                status = drawio_validator.validate(instance_file)\n                if not status:\n                    logger.info(f'INVALID: {self.rel_dir(instance_file)}')\n                    return False\n                else:\n                    logger.info(f'VALID: {self.rel_dir(instance_file)}')\n\n            else:\n                logger.debug(f'Unsupported extension of the instance file: {instance_file}, will not be validated.')\n\n        return True\n\n    def _update_templates(\n        self, all_versioned_templates: Dict[str, Dict[str, str]], templates: List[str], instance_version: str\n    ) -> None:\n        all_versioned_templates[instance_version] = {}\n        all_drawio_templates = list(filter(lambda p: p.suffix == const.DRAWIO_FILE_EXT, templates))\n        all_md_templates = list(filter(lambda p: p.suffix == const.MARKDOWN_FILE_EXT, templates))\n        if all_drawio_templates:\n            all_versioned_templates[instance_version]['drawio'] = all_drawio_templates[0]\n        if all_md_templates:\n            all_versioned_templates[instance_version]['md'] = all_md_templates[0]\n\n    def validate(\n        self,\n        recurse: bool,\n        readme_validate: bool,\n        relative_excludes: List[pathlib.Path],\n        template_version: str,\n        ignore: str\n    ) -> int:\n\"\"\"Run validation based on available templates.\"\"\"\n        paths = []\n        if self.task_name:\n            if not self.task_path.is_dir():\n                raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n            paths = [self.task_path]\n        else:\n            for path in self.trestle_root.iterdir():\n                relative_path = path.relative_to(self.trestle_root)\n                # Files in the root directory must be exclused\n                if path.is_file():\n                    continue\n                if not file_utils.is_directory_name_allowed(path):\n                    continue\n                if str(relative_path).rstrip('/') in const.MODEL_DIR_LIST:\n                    continue\n                if (relative_path in relative_excludes):\n                    continue\n                if not file_utils.is_hidden(path):\n                    paths.append(path)\n\n        for path in paths:\n            try:\n                valid = self._validate_dir(path, recurse, readme_validate, relative_excludes, template_version, ignore)\n                if not valid:\n                    logger.info(f'validation failed on {path}')\n                    return CmdReturnCodes.DOCUMENTS_VALIDATION_ERROR.value\n            except Exception as e:\n                raise TrestleError(f'Error during header validation on {path} {e}')\n\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.create_sample","title":"create_sample(self)","text":"

                                                                            Create sample object, this always defaults to markdown.

                                                                            Source code in trestle/core/commands/author/headers.py
                                                                            def create_sample(self) -> int:\n\"\"\"Create sample object, this always defaults to markdown.\"\"\"\n    logger.info('Header only validation does not support sample creation.')\n    logger.info('Exiting')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.setup","title":"setup(self, template_version)","text":"

                                                                            Create template directory and templates.

                                                                            Source code in trestle/core/commands/author/headers.py
                                                                            def setup(self, template_version: str) -> int:\n\"\"\"Create template directory and templates.\"\"\"\n    # Step 1 - validation\n\n    if self.task_name and not self.task_path.exists():\n        self.task_path.mkdir(exist_ok=True, parents=True)\n    elif self.task_name and self.task_path.is_file():\n        raise TrestleError(f'Task path: {self.rel_dir(self.task_path)} is a file not a directory.')\n\n    if not self.template_dir.exists():\n        self.template_dir.mkdir(exist_ok=True, parents=True)\n    logger.info(f'Populating template files to {self.rel_dir(self.template_dir)}')\n    for template in author_const.REFERENCE_TEMPLATES.values():\n        destination_path = self.template_dir / template\n        TemplateVersioning.write_versioned_template(template, self.template_dir, destination_path, template_version)\n\n        logger.info(f'Template directory populated {self.rel_dir(destination_path)}')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.template_validate","title":"template_validate(self)","text":"

                                                                            Validate the integrity of the template files.

                                                                            Source code in trestle/core/commands/author/headers.py
                                                                            def template_validate(self) -> int:\n\"\"\"Validate the integrity of the template files.\"\"\"\n    logger.info('Checking template file integrity')\n    for template_file in self.template_dir.iterdir():\n        if (template_file.name not in author_const.REFERENCE_TEMPLATES.values()\n                and template_file.name.lower() != 'readme.md'):\n            raise TrestleError(f'Unexpected template file {self.rel_dir(template_file)}')\n\n        if template_file.suffix == const.MARKDOWN_FILE_EXT:\n            try:\n                md_api = MarkdownAPI()\n                md_api.load_validator_with_template(template_file, True, False)\n            except Exception as ex:\n                raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n        elif template_file.suffix == const.DRAWIO_FILE_EXT:\n            try:\n                _ = DrawIOMetadataValidator(template_file)\n            except Exception as ex:\n                raise TrestleError(f'Template for task {self.task_name} failed to validate due to {ex}')\n\n    logger.info('Templates validated')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.headers/#trestle.core.commands.author.headers.Headers.validate","title":"validate(self, recurse, readme_validate, relative_excludes, template_version, ignore)","text":"

                                                                            Run validation based on available templates.

                                                                            Source code in trestle/core/commands/author/headers.py
                                                                            def validate(\n    self,\n    recurse: bool,\n    readme_validate: bool,\n    relative_excludes: List[pathlib.Path],\n    template_version: str,\n    ignore: str\n) -> int:\n\"\"\"Run validation based on available templates.\"\"\"\n    paths = []\n    if self.task_name:\n        if not self.task_path.is_dir():\n            raise TrestleError(f'Task directory {self.rel_dir(self.task_path)} does not exist. Exiting validate.')\n\n        paths = [self.task_path]\n    else:\n        for path in self.trestle_root.iterdir():\n            relative_path = path.relative_to(self.trestle_root)\n            # Files in the root directory must be exclused\n            if path.is_file():\n                continue\n            if not file_utils.is_directory_name_allowed(path):\n                continue\n            if str(relative_path).rstrip('/') in const.MODEL_DIR_LIST:\n                continue\n            if (relative_path in relative_excludes):\n                continue\n            if not file_utils.is_hidden(path):\n                paths.append(path)\n\n    for path in paths:\n        try:\n            valid = self._validate_dir(path, recurse, readme_validate, relative_excludes, template_version, ignore)\n            if not valid:\n                logger.info(f'validation failed on {path}')\n                return CmdReturnCodes.DOCUMENTS_VALIDATION_ERROR.value\n        except Exception as e:\n            raise TrestleError(f'Error during header validation on {path} {e}')\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.jinja/","title":"jinja","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja","title":"trestle.core.commands.author.jinja","text":"

                                                                            Trestle Commands.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd","title":" JinjaCmd (CommandPlusDocs) ","text":"

                                                                            Transform an input template to an output document using jinja templating.

                                                                            Source code in trestle/core/commands/author/jinja.py
                                                                            class JinjaCmd(CommandPlusDocs):\n\"\"\"Transform an input template to an output document using jinja templating.\"\"\"\n\n    max_recursion_depth = 2\n\n    name = 'jinja'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-i', '--input', help='Input jinja template, relative to trestle root', required=True)\n        self.add_argument('-o', '--output', help='Output template, relative to trestle root.', required=True)\n        self.add_argument(\n            '-lut',\n            '--look-up-table',\n            help='Key-value pair table, stored as yaml, to be passed to jinja as variables',\n            required=False\n        )\n        self.add_argument(\n            '-elp',\n            '--external-lut-prefix',\n            help='Prefix paths for LUT, to maintain compatibility with other templating systems',\n            required=False\n        )\n        self.add_argument(\n            '-nc',\n            '--number-captions',\n            help='Add incremental numbering to table and image captions, in the form Table n - ... and Figure n - ...',\n            action='store_true'\n        )\n        self.add_argument(\n            '-bf',\n            '--bracket-format',\n            help='With -sv, allows brackets around value, e.g. [.] or ((.)), with the dot representing the value.',\n            required=False\n        )\n        self.add_argument(\n            '-vap',\n            '--value-assigned-prefix',\n            help='Places a prefix in front of the parameter string if a value has been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-vnap',\n            '--value-not-assigned-prefix',\n            help='Places a prefix in front of the parameter string if a value has *not* been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-ssp', '--system-security-plan', help='An optional SSP to be passed', default=None, required=False\n        )\n        self.add_argument('-p', '--profile', help='An optional profile to be passed', default=None, required=False)\n        self.add_argument(\n            '-dp',\n            '--docs-profile',\n            help='Output profile controls to separate markdown files',\n            action='store_true',\n            required=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> None:\n        try:\n            log.set_log_level_from_args(args)\n            logger.debug(f'Starting {self.name} command')\n            input_path = pathlib.Path(args.input)\n            output_path = pathlib.Path(args.output)\n\n            logger.debug(f'input_path: {input_path}')\n            logger.debug(f'output_path: {output_path}')\n            logger.debug(f'system_security_plan path: {args.system_security_plan}')\n            logger.debug(f'profile: {args.profile}')\n            logger.debug(f'docs_profile: {args.docs_profile}')\n            logger.debug(f'lookup_table: {args.look_up_table}')\n\n            if args.system_security_plan and args.docs_profile:\n                raise TrestleIncorrectArgsError('Output to multiple files is possible with profile only.')\n\n            if args.docs_profile and not args.profile:\n                raise TrestleIncorrectArgsError('Profile must be provided to output to multiple files.')\n\n            lut = {}\n            if args.look_up_table:\n                lut_table = pathlib.Path(args.look_up_table)\n                lookup_table_path = pathlib.Path.cwd() / lut_table\n                lut = JinjaCmd.load_LUT(lookup_table_path, args.external_lut_prefix)\n\n            if args.profile and args.docs_profile:\n                return JinjaCmd.jinja_multiple_md(\n                    pathlib.Path(args.trestle_root),\n                    input_path,\n                    output_path,\n                    args.profile,\n                    lut,\n                    parameters_formatting=args.bracket_format,\n                    value_assigned_prefix=args.value_assigned_prefix,\n                    value_not_assigned_prefix=args.value_not_assigned_prefix\n                )\n\n            return JinjaCmd.jinja_ify(\n                pathlib.Path(args.trestle_root),\n                input_path,\n                output_path,\n                args.system_security_plan,\n                args.profile,\n                lut,\n                number_captions=args.number_captions,\n                parameters_formatting=args.bracket_format,\n                value_assigned_prefix=args.value_assigned_prefix,\n                value_not_assigned_prefix=args.value_not_assigned_prefix\n            )\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(  # type: ignore\n                e, logger, 'Error while generating markdown via Jinja template'\n            )\n\n    @staticmethod\n    def load_LUT(path: pathlib.Path, prefix: Optional[str]) -> Dict[str, Any]:  # noqa: N802\n\"\"\"Load a Yaml lookup table from file.\"\"\"\n        yaml = YAML()\n        lut = yaml.load(path.open('r', encoding=const.FILE_ENCODING))\n        if prefix:\n            prefixes = prefix.split('.')\n            while prefixes:\n                old_lut = lut\n                lut[prefixes.pop(-1)] = old_lut\n\n        return lut\n\n    @staticmethod\n    def jinja_ify(\n        trestle_root: pathlib.Path,\n        r_input_file: pathlib.Path,\n        r_output_file: pathlib.Path,\n        ssp: Optional[str],\n        profile: Optional[str],\n        lut: Dict[str, Any],\n        number_captions: Optional[bool] = False,\n        parameters_formatting: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> int:\n\"\"\"Run jinja over an input file with additional booleans.\"\"\"\n        template_folder = pathlib.Path.cwd()\n        jinja_env = Environment(\n            loader=FileSystemLoader(template_folder),\n            extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n            trim_blocks=True,\n            autoescape=True\n        )\n        template = jinja_env.get_template(str(r_input_file))\n        # create boolean dict\n        if operator.xor(bool(ssp), bool(profile)):\n            raise TrestleIncorrectArgsError('Both SSP and profile should be provided or not at all')\n\n        if ssp:\n            # name lookup\n            ssp_data, _ = load_validate_model_name(trestle_root, ssp, SystemSecurityPlan)\n            lut['ssp'] = ssp_data\n            profile_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, profile, Profile)\n            profile_resolver = ProfileResolver()\n            resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n                trestle_root,\n                profile_path,\n                False,\n                False,\n                parameters_formatting,\n                ParameterRep.ASSIGNMENT_FORM,\n                False,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n\n            ssp_writer = SSPMarkdownWriter(trestle_root)\n            ssp_writer.set_ssp(ssp_data)\n            ssp_writer.set_catalog(resolved_catalog)\n            lut['catalog'] = resolved_catalog\n            lut['catalog_interface'] = CatalogInterface(resolved_catalog)\n            lut['control_interface'] = ControlInterface()\n            lut['control_writer'] = DocsControlWriter()\n            lut['ssp_md_writer'] = ssp_writer\n\n        output = JinjaCmd.render_template(template, lut, template_folder)\n\n        output_file = trestle_root / r_output_file\n        if number_captions:\n            output_file.open('w', encoding=const.FILE_ENCODING).write(_number_captions(output))\n        else:\n            output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def jinja_multiple_md(\n        trestle_root: pathlib.Path,\n        r_input_file: pathlib.Path,\n        r_output_file: pathlib.Path,\n        profile_name: Optional[str],\n        lut: Dict[str, Any],\n        parameters_formatting: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> int:\n\"\"\"Output profile as multiple markdown files using Jinja.\"\"\"\n        template_folder = pathlib.Path.cwd()\n\n        # Output to multiple markdown files\n        profile, profile_path = ModelUtils.load_model_for_class(trestle_root, profile_name, Profile)\n        profile_resolver = ProfileResolver()\n        resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            False,\n            False,\n            parameters_formatting,\n            ParameterRep.ASSIGNMENT_FORM,\n            False,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        catalog_interface = CatalogInterface(resolved_catalog)\n\n        # Generate a single markdown page for each control per each group\n        for group in catalog_interface.get_all_groups_from_catalog():\n            for control in catalog_interface.get_sorted_controls_in_group(group.id):\n                _, group_title, _ = catalog_interface.get_group_info_by_control(control.id)\n                group_dir = r_output_file\n                control_path = catalog_interface.get_control_path(control.id)\n                for sub_dir in control_path:\n                    group_dir = group_dir / sub_dir\n                    if not group_dir.exists():\n                        group_dir.mkdir(parents=True, exist_ok=True)\n\n                control_writer = DocsControlWriter()\n\n                jinja_env = Environment(\n                    loader=FileSystemLoader(template_folder),\n                    extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n                    trim_blocks=True,\n                    autoescape=True\n                )\n                template = jinja_env.get_template(str(r_input_file))\n                lut['catalog_interface'] = catalog_interface\n                lut['control_interface'] = ControlInterface()\n                lut['control_writer'] = control_writer\n                lut['control'] = control\n                lut['profile'] = profile\n                lut['group_title'] = group_title\n                output = JinjaCmd.render_template(template, lut, template_folder)\n\n                output_file = trestle_root / group_dir / pathlib.Path(control.id + const.MARKDOWN_FILE_EXT)\n                output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    @staticmethod\n    def render_template(template: Template, lut: Dict[str, Any], template_folder: pathlib.Path) -> str:\n\"\"\"Render template.\"\"\"\n        new_output = template.render(**lut)\n        output = ''\n        # This recursion allows nesting within expressions (e.g. an expression can contain jinja templates).\n        error_countdown = JinjaCmd.max_recursion_depth\n        while new_output != output and error_countdown > 0:\n            error_countdown = error_countdown - 1\n            output = new_output\n            random_name = uuid.uuid4()  # Should be random and not used.\n            dict_loader = DictLoader({str(random_name): new_output})\n            jinja_env = Environment(\n                loader=ChoiceLoader([dict_loader, FileSystemLoader(template_folder)]),\n                extensions=[MDCleanInclude, MDSectionInclude, MDDatestamp],\n                autoescape=True,\n                trim_blocks=True\n            )\n            template = jinja_env.get_template(str(random_name))\n            new_output = template.render(**lut)\n\n        return output\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.max_recursion_depth","title":"max_recursion_depth","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.jinja_ify","title":"jinja_ify(trestle_root, r_input_file, r_output_file, ssp, profile, lut, number_captions=False, parameters_formatting=None, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                                                            Run jinja over an input file with additional booleans.

                                                                            Source code in trestle/core/commands/author/jinja.py
                                                                            @staticmethod\ndef jinja_ify(\n    trestle_root: pathlib.Path,\n    r_input_file: pathlib.Path,\n    r_output_file: pathlib.Path,\n    ssp: Optional[str],\n    profile: Optional[str],\n    lut: Dict[str, Any],\n    number_captions: Optional[bool] = False,\n    parameters_formatting: Optional[str] = None,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> int:\n\"\"\"Run jinja over an input file with additional booleans.\"\"\"\n    template_folder = pathlib.Path.cwd()\n    jinja_env = Environment(\n        loader=FileSystemLoader(template_folder),\n        extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n        trim_blocks=True,\n        autoescape=True\n    )\n    template = jinja_env.get_template(str(r_input_file))\n    # create boolean dict\n    if operator.xor(bool(ssp), bool(profile)):\n        raise TrestleIncorrectArgsError('Both SSP and profile should be provided or not at all')\n\n    if ssp:\n        # name lookup\n        ssp_data, _ = load_validate_model_name(trestle_root, ssp, SystemSecurityPlan)\n        lut['ssp'] = ssp_data\n        profile_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, profile, Profile)\n        profile_resolver = ProfileResolver()\n        resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            False,\n            False,\n            parameters_formatting,\n            ParameterRep.ASSIGNMENT_FORM,\n            False,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n\n        ssp_writer = SSPMarkdownWriter(trestle_root)\n        ssp_writer.set_ssp(ssp_data)\n        ssp_writer.set_catalog(resolved_catalog)\n        lut['catalog'] = resolved_catalog\n        lut['catalog_interface'] = CatalogInterface(resolved_catalog)\n        lut['control_interface'] = ControlInterface()\n        lut['control_writer'] = DocsControlWriter()\n        lut['ssp_md_writer'] = ssp_writer\n\n    output = JinjaCmd.render_template(template, lut, template_folder)\n\n    output_file = trestle_root / r_output_file\n    if number_captions:\n        output_file.open('w', encoding=const.FILE_ENCODING).write(_number_captions(output))\n    else:\n        output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.jinja_multiple_md","title":"jinja_multiple_md(trestle_root, r_input_file, r_output_file, profile_name, lut, parameters_formatting=None, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                                                            Output profile as multiple markdown files using Jinja.

                                                                            Source code in trestle/core/commands/author/jinja.py
                                                                            @staticmethod\ndef jinja_multiple_md(\n    trestle_root: pathlib.Path,\n    r_input_file: pathlib.Path,\n    r_output_file: pathlib.Path,\n    profile_name: Optional[str],\n    lut: Dict[str, Any],\n    parameters_formatting: Optional[str] = None,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> int:\n\"\"\"Output profile as multiple markdown files using Jinja.\"\"\"\n    template_folder = pathlib.Path.cwd()\n\n    # Output to multiple markdown files\n    profile, profile_path = ModelUtils.load_model_for_class(trestle_root, profile_name, Profile)\n    profile_resolver = ProfileResolver()\n    resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n        trestle_root,\n        profile_path,\n        False,\n        False,\n        parameters_formatting,\n        ParameterRep.ASSIGNMENT_FORM,\n        False,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    catalog_interface = CatalogInterface(resolved_catalog)\n\n    # Generate a single markdown page for each control per each group\n    for group in catalog_interface.get_all_groups_from_catalog():\n        for control in catalog_interface.get_sorted_controls_in_group(group.id):\n            _, group_title, _ = catalog_interface.get_group_info_by_control(control.id)\n            group_dir = r_output_file\n            control_path = catalog_interface.get_control_path(control.id)\n            for sub_dir in control_path:\n                group_dir = group_dir / sub_dir\n                if not group_dir.exists():\n                    group_dir.mkdir(parents=True, exist_ok=True)\n\n            control_writer = DocsControlWriter()\n\n            jinja_env = Environment(\n                loader=FileSystemLoader(template_folder),\n                extensions=[MDSectionInclude, MDCleanInclude, MDDatestamp],\n                trim_blocks=True,\n                autoescape=True\n            )\n            template = jinja_env.get_template(str(r_input_file))\n            lut['catalog_interface'] = catalog_interface\n            lut['control_interface'] = ControlInterface()\n            lut['control_writer'] = control_writer\n            lut['control'] = control\n            lut['profile'] = profile\n            lut['group_title'] = group_title\n            output = JinjaCmd.render_template(template, lut, template_folder)\n\n            output_file = trestle_root / group_dir / pathlib.Path(control.id + const.MARKDOWN_FILE_EXT)\n            output_file.open('w', encoding=const.FILE_ENCODING).write(output)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.load_LUT","title":"load_LUT(path, prefix) staticmethod","text":"

                                                                            Load a Yaml lookup table from file.

                                                                            Source code in trestle/core/commands/author/jinja.py
                                                                            @staticmethod\ndef load_LUT(path: pathlib.Path, prefix: Optional[str]) -> Dict[str, Any]:  # noqa: N802\n\"\"\"Load a Yaml lookup table from file.\"\"\"\n    yaml = YAML()\n    lut = yaml.load(path.open('r', encoding=const.FILE_ENCODING))\n    if prefix:\n        prefixes = prefix.split('.')\n        while prefixes:\n            old_lut = lut\n            lut[prefixes.pop(-1)] = old_lut\n\n    return lut\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.jinja/#trestle.core.commands.author.jinja.JinjaCmd.render_template","title":"render_template(template, lut, template_folder) staticmethod","text":"

                                                                            Render template.

                                                                            Source code in trestle/core/commands/author/jinja.py
                                                                            @staticmethod\ndef render_template(template: Template, lut: Dict[str, Any], template_folder: pathlib.Path) -> str:\n\"\"\"Render template.\"\"\"\n    new_output = template.render(**lut)\n    output = ''\n    # This recursion allows nesting within expressions (e.g. an expression can contain jinja templates).\n    error_countdown = JinjaCmd.max_recursion_depth\n    while new_output != output and error_countdown > 0:\n        error_countdown = error_countdown - 1\n        output = new_output\n        random_name = uuid.uuid4()  # Should be random and not used.\n        dict_loader = DictLoader({str(random_name): new_output})\n        jinja_env = Environment(\n            loader=ChoiceLoader([dict_loader, FileSystemLoader(template_folder)]),\n            extensions=[MDCleanInclude, MDSectionInclude, MDDatestamp],\n            autoescape=True,\n            trim_blocks=True\n        )\n        template = jinja_env.get_template(str(random_name))\n        new_output = template.render(**lut)\n\n    return output\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/","title":"prof","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof","title":"trestle.core.commands.author.prof","text":"

                                                                            Author commands to generate profile as markdown and assemble to json after edit.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble","title":" ProfileAssemble (AuthorCommonCommand) ","text":"

                                                                            Assemble markdown files of controls into a Profile json file.

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            class ProfileAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into a Profile json file.\"\"\"\n\n    name = 'profile-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the profile model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the source markdown file directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json Profile (ok to overwrite original)'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-sp', '--set-parameters', action='store_true', help=const.HELP_SET_PARAMS, required=False)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n        self.add_argument('-s', '--sections', help=const.HELP_SECTIONS, required=False, type=str)\n        self.add_argument('-rs', '--required-sections', help=const.HELP_REQUIRED_SECTIONS, required=False, type=str)\n        self.add_argument('-as', '--allowed-sections', help=const.HELP_ALLOWED_SECTIONS, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n            return self.assemble_profile(\n                trestle_root=trestle_root,\n                parent_prof_name=args.name,\n                md_name=args.markdown,\n                assem_prof_name=args.output,\n                set_parameters_flag=args.set_parameters,\n                regenerate=args.regenerate,\n                version=args.version,\n                sections_dict=comma_colon_sep_to_dict(args.sections),\n                required_sections=comma_sep_to_list(args.required_sections),\n                allowed_sections=args.allowed_sections\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Assembly of markdown to profile failed')\n\n    @staticmethod\n    def _update_alter_adds(profile: prof.Profile, alters: List[prof.Alter], alter_dict: Dict) -> None:\n        for new_alter in alters:\n            alter = alter_dict.get(new_alter.control_id, None)\n            if not alter:\n                # the control did not have alters, so add\n                alter = prof.Alter(control_id=new_alter.control_id)\n            # even though we removed adds at start, we may have added one already\n            if alter.adds:\n                alter.adds.extend(new_alter.adds)\n            else:\n                alter.adds = new_alter.adds\n            # update the dict with the new alter with its added adds\n            alter_dict[new_alter.control_id] = alter\n\n    @staticmethod\n    def _replace_alter_adds(profile: prof.Profile, alters: List[prof.Alter]) -> bool:\n\"\"\"Replace the alter adds in the orig_profile with the new ones and return True if changed.\"\"\"\n        changed = False\n        if not profile.modify:\n            profile.modify = prof.Modify(alters=alters)\n            if alters:\n                changed = True\n        elif not profile.modify.alters:\n            profile.modify.alters = alters\n            if alters:\n                changed = True\n        else:\n            alter_dict = {}\n            # if an alter has adds - remove them up front and build dict of alters by control id\n            for alter in profile.modify.alters:\n                alter.adds = None\n                alter_dict[alter.control_id] = alter\n            # now go through new alters and add them to each control in dict by control id\n            ProfileAssemble._update_alter_adds(profile, alters, alter_dict)\n            # get the new list of alters from the dict and update profile\n            new_alters = list(alter_dict.values())\n            # special case, if all adds were deleted remove such alters completely\n            new_alters = list(filter(lambda alt: alt.adds or alt.removes, new_alters))\n            if profile.modify.alters != new_alters:\n                changed = True\n            profile.modify.alters = none_if_empty(new_alters)\n        return changed\n\n    @staticmethod\n    def _replace_modify_set_params(\n        profile: prof.Profile, param_dict: Dict[str, Any], param_map: Dict[str, str]\n    ) -> bool:\n\"\"\"\n        Replace the set_params in the profile with list and values from markdown.\n\n        Notes:\n            Returns whether or not change was made.\n        \"\"\"\n        changed = False\n        if param_dict:\n            if not profile.modify:\n                profile.modify = prof.Modify()\n            new_set_params: List[prof.SetParameter] = []\n            for key, sub_param_dict in param_dict.items():\n                if sub_param_dict:\n                    sub_param_dict['id'] = key\n                    param = ModelUtils.dict_to_parameter(sub_param_dict)\n                    new_set_params.append(\n                        prof.SetParameter(\n                            param_id=key,\n                            label=param.label,\n                            values=param.values,\n                            select=param.select,\n                            props=param.props\n                        )\n                    )\n            if profile.modify.set_parameters != new_set_params:\n                changed = True\n            # sort the params first by control sorting then by param_id\n            profile.modify.set_parameters = sorted(\n                new_set_params, key=lambda param: (param_map[param.param_id], param.param_id)\n            )\n        if profile.modify:\n            profile.modify.set_parameters = none_if_empty(profile.modify.set_parameters)\n        return changed\n\n    @staticmethod\n    def assemble_profile(\n        trestle_root: pathlib.Path,\n        parent_prof_name: str,\n        md_name: str,\n        assem_prof_name: str,\n        set_parameters_flag: bool,\n        regenerate: bool,\n        version: Optional[str],\n        sections_dict: Dict[str, str],\n        required_sections: List[str],\n        allowed_sections: Optional[List[str]]\n    ) -> int:\n\"\"\"\n        Assemble the markdown directory into a json profile model file.\n\n        Args:\n            trestle_root: The trestle root directory\n            parent_prof_name: Optional name of profile used to generate the markdown (default is assem_prof_name)\n            md_name: The name of the directory containing the markdown control files for the profile\n            assem_prof_name: The name of the assembled profile.  It can be the same as the parent to overwrite\n            set_parameters_flag: Use the params and props in yaml header to add or alter setparameters in the profile\n            regenerate: Whether to regenerate the uuid's in the profile\n            version: Optional version for the assembled profile\n            sections_dict: Optional map of short name to long name for sections\n            required_sections: List of required sections in assembled profile, as comma-separated short names\n            allowed_sections: Optional list of section short names that are allowed, as comma-separated short names\n\n        Returns:\n            0 on success, 1 otherwise\n\n        Notes:\n            There must already be a profile model and it will either be updated or a new json profile created.\n            The generated markdown has the current values for parameters of controls being imported, as set by\n            the original catalog and any intermediate profiles.  It also shows the current SetParameters being applied\n            by this profile.  That list of SetParameters can be edited by changing the assigned values and adding or\n            removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n            in the assembled profile if the --set-parameters option is specified.\n        \"\"\"\n        md_dir = trestle_root / md_name\n        if not md_dir.exists():\n            raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n        if not parent_prof_name:\n            parent_prof_name = assem_prof_name\n\n        parent_prof_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, parent_prof_name, prof.Profile)\n        if parent_prof_path is None:\n            raise TrestleError(f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.')\n\n        parent_prof, parent_prof_path = load_validate_model_name(trestle_root, parent_prof_name, prof.Profile)\n        new_content_type = FileContentType.path_to_content_type(parent_prof_path)\n\n        catalog = ProfileResolver.get_resolved_profile_catalog(\n            trestle_root, parent_prof_path, param_rep=ParameterRep.LEAVE_MOUSTACHE\n        )\n\n        context = ControlContext.generate(\n            ContextPurpose.PROFILE, to_markdown=False, trestle_root=trestle_root, md_root=md_dir\n        )\n        context.sections_dict = sections_dict\n        context.required_sections = required_sections\n\n        # load the editable sections of the markdown and create Adds for them\n        # then overwrite the Adds in the existing profile with the new ones\n        # keep track if any changes were made\n        catalog_api = CatalogAPI(catalog=catalog, context=context)\n        found_alters, param_dict, param_map = catalog_api.read_additional_content_from_md(label_as_key=True)\n\n        if allowed_sections is not None:\n            for bad_part in [\n                    part for alter in found_alters for add in as_list(alter.adds)\n                    for part in as_filtered_list(add.parts, lambda a: a.name not in allowed_sections)  # type: ignore\n            ]:\n                raise TrestleError(f'Profile has alter with name {bad_part.name} not in allowed sections.')\n\n        ProfileAssemble._replace_alter_adds(parent_prof, found_alters)\n        if set_parameters_flag:\n            ProfileAssemble._replace_modify_set_params(parent_prof, param_dict, param_map)\n\n        if version:\n            parent_prof.metadata.version = version\n\n        parent_prof.metadata.oscal_version = OSCAL_VERSION\n\n        assem_prof_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, assem_prof_name, prof.Profile, new_content_type\n        )\n\n        if assem_prof_path.exists():\n            _, _, existing_prof = ModelUtils.load_distributed(assem_prof_path, trestle_root)\n            if ModelUtils.models_are_equivalent(existing_prof, parent_prof):  # type: ignore\n                logger.info('Assembled profile is no different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n\n        if regenerate:\n            parent_prof, _, _ = ModelUtils.regenerate_uuids(parent_prof)\n        ModelUtils.update_last_modified(parent_prof)  # type: ignore\n\n        if assem_prof_path.parent.exists():\n            logger.info('Creating profile from markdown and destination profile exists, so updating.')\n            shutil.rmtree(str(assem_prof_path.parent))\n\n        assem_prof_path.parent.mkdir(parents=True, exist_ok=True)\n        parent_prof.oscal_write(assem_prof_path)  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileAssemble.assemble_profile","title":"assemble_profile(trestle_root, parent_prof_name, md_name, assem_prof_name, set_parameters_flag, regenerate, version, sections_dict, required_sections, allowed_sections) staticmethod","text":"

                                                                            Assemble the markdown directory into a json profile model file.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            The trestle root directory

                                                                            required parent_prof_name str

                                                                            Optional name of profile used to generate the markdown (default is assem_prof_name)

                                                                            required md_name str

                                                                            The name of the directory containing the markdown control files for the profile

                                                                            required assem_prof_name str

                                                                            The name of the assembled profile. It can be the same as the parent to overwrite

                                                                            required set_parameters_flag bool

                                                                            Use the params and props in yaml header to add or alter setparameters in the profile

                                                                            required regenerate bool

                                                                            Whether to regenerate the uuid's in the profile

                                                                            required version Optional[str]

                                                                            Optional version for the assembled profile

                                                                            required sections_dict Dict[str, str]

                                                                            Optional map of short name to long name for sections

                                                                            required required_sections List[str]

                                                                            List of required sections in assembled profile, as comma-separated short names

                                                                            required allowed_sections Optional[List[str]]

                                                                            Optional list of section short names that are allowed, as comma-separated short names

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success, 1 otherwise

                                                                            Notes

                                                                            There must already be a profile model and it will either be updated or a new json profile created. The generated markdown has the current values for parameters of controls being imported, as set by the original catalog and any intermediate profiles. It also shows the current SetParameters being applied by this profile. That list of SetParameters can be edited by changing the assigned values and adding or removing SetParameters from that list. During assembly that list will be used to create the SetParameters in the assembled profile if the --set-parameters option is specified.

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            @staticmethod\ndef assemble_profile(\n    trestle_root: pathlib.Path,\n    parent_prof_name: str,\n    md_name: str,\n    assem_prof_name: str,\n    set_parameters_flag: bool,\n    regenerate: bool,\n    version: Optional[str],\n    sections_dict: Dict[str, str],\n    required_sections: List[str],\n    allowed_sections: Optional[List[str]]\n) -> int:\n\"\"\"\n    Assemble the markdown directory into a json profile model file.\n\n    Args:\n        trestle_root: The trestle root directory\n        parent_prof_name: Optional name of profile used to generate the markdown (default is assem_prof_name)\n        md_name: The name of the directory containing the markdown control files for the profile\n        assem_prof_name: The name of the assembled profile.  It can be the same as the parent to overwrite\n        set_parameters_flag: Use the params and props in yaml header to add or alter setparameters in the profile\n        regenerate: Whether to regenerate the uuid's in the profile\n        version: Optional version for the assembled profile\n        sections_dict: Optional map of short name to long name for sections\n        required_sections: List of required sections in assembled profile, as comma-separated short names\n        allowed_sections: Optional list of section short names that are allowed, as comma-separated short names\n\n    Returns:\n        0 on success, 1 otherwise\n\n    Notes:\n        There must already be a profile model and it will either be updated or a new json profile created.\n        The generated markdown has the current values for parameters of controls being imported, as set by\n        the original catalog and any intermediate profiles.  It also shows the current SetParameters being applied\n        by this profile.  That list of SetParameters can be edited by changing the assigned values and adding or\n        removing SetParameters from that list.  During assembly that list will be used to create the SetParameters\n        in the assembled profile if the --set-parameters option is specified.\n    \"\"\"\n    md_dir = trestle_root / md_name\n    if not md_dir.exists():\n        raise TrestleError(f'Markdown directory {md_name} does not exist.')\n\n    if not parent_prof_name:\n        parent_prof_name = assem_prof_name\n\n    parent_prof_path = ModelUtils.get_model_path_for_name_and_class(trestle_root, parent_prof_name, prof.Profile)\n    if parent_prof_path is None:\n        raise TrestleError(f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.')\n\n    parent_prof, parent_prof_path = load_validate_model_name(trestle_root, parent_prof_name, prof.Profile)\n    new_content_type = FileContentType.path_to_content_type(parent_prof_path)\n\n    catalog = ProfileResolver.get_resolved_profile_catalog(\n        trestle_root, parent_prof_path, param_rep=ParameterRep.LEAVE_MOUSTACHE\n    )\n\n    context = ControlContext.generate(\n        ContextPurpose.PROFILE, to_markdown=False, trestle_root=trestle_root, md_root=md_dir\n    )\n    context.sections_dict = sections_dict\n    context.required_sections = required_sections\n\n    # load the editable sections of the markdown and create Adds for them\n    # then overwrite the Adds in the existing profile with the new ones\n    # keep track if any changes were made\n    catalog_api = CatalogAPI(catalog=catalog, context=context)\n    found_alters, param_dict, param_map = catalog_api.read_additional_content_from_md(label_as_key=True)\n\n    if allowed_sections is not None:\n        for bad_part in [\n                part for alter in found_alters for add in as_list(alter.adds)\n                for part in as_filtered_list(add.parts, lambda a: a.name not in allowed_sections)  # type: ignore\n        ]:\n            raise TrestleError(f'Profile has alter with name {bad_part.name} not in allowed sections.')\n\n    ProfileAssemble._replace_alter_adds(parent_prof, found_alters)\n    if set_parameters_flag:\n        ProfileAssemble._replace_modify_set_params(parent_prof, param_dict, param_map)\n\n    if version:\n        parent_prof.metadata.version = version\n\n    parent_prof.metadata.oscal_version = OSCAL_VERSION\n\n    assem_prof_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, assem_prof_name, prof.Profile, new_content_type\n    )\n\n    if assem_prof_path.exists():\n        _, _, existing_prof = ModelUtils.load_distributed(assem_prof_path, trestle_root)\n        if ModelUtils.models_are_equivalent(existing_prof, parent_prof):  # type: ignore\n            logger.info('Assembled profile is no different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n\n    if regenerate:\n        parent_prof, _, _ = ModelUtils.regenerate_uuids(parent_prof)\n    ModelUtils.update_last_modified(parent_prof)  # type: ignore\n\n    if assem_prof_path.parent.exists():\n        logger.info('Creating profile from markdown and destination profile exists, so updating.')\n        shutil.rmtree(str(assem_prof_path.parent))\n\n    assem_prof_path.parent.mkdir(parents=True, exist_ok=True)\n    parent_prof.oscal_write(assem_prof_path)  # type: ignore\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate","title":" ProfileGenerate (AuthorCommonCommand) ","text":"

                                                                            Generate profile in markdown form from a profile in the trestle workspace.

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            class ProfileGenerate(AuthorCommonCommand):\n\"\"\"Generate profile in markdown form from a profile in the trestle workspace.\"\"\"\n\n    name = 'profile-generate'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the source profile model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument('-o', '--output', help=const.HELP_MARKDOWN_NAME, required=True, type=str)\n        self.add_argument('-y', '--yaml-header', help=const.HELP_YAML_PATH, required=False, type=str)\n        self.add_argument(\n            '-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true', default=False\n        )\n        self.add_argument(\n            '-ohv',\n            '--overwrite-header-values',\n            help=const.HELP_OVERWRITE_HEADER_VALUES,\n            required=False,\n            action='store_true',\n            default=False\n        )\n        self.add_argument('-s', '--sections', help=const.HELP_SECTIONS, required=False, type=str)\n        self.add_argument('-rs', '--required-sections', help=const.HELP_REQUIRED_SECTIONS, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root: pathlib.Path = args.trestle_root\n            if not file_utils.is_directory_name_allowed(args.output):\n                raise TrestleError(f'{args.output} is not an allowed directory name')\n\n            yaml_header: Dict[str, Any] = {}\n            if args.yaml_header:\n                try:\n                    logging.debug(f'Loading yaml header file {args.yaml_header}')\n                    yaml = YAML()\n                    yaml_header = yaml.load(pathlib.Path(args.yaml_header).open('r'))\n                except YAMLError as e:\n                    raise TrestleError(f'YAML error loading yaml header for ssp generation: {e}')\n\n            if args.force_overwrite:\n                try:\n                    logger.info(f'Overwriting the content in {args.output}.')\n                    clear_folder(pathlib.Path(args.output))\n                except TrestleError as e:  # pragma: no cover\n                    raise TrestleError(f'Unable to overwrite contents of {args.output}: {e}')\n\n            # combine command line sections with any in the yaml header, with priority to command line\n            sections_dict = comma_colon_sep_to_dict(args.sections)\n\n            profile_path = trestle_root / f'profiles/{args.name}/profile.json'\n\n            markdown_path = trestle_root / args.output\n\n            return self.generate_markdown(\n                trestle_root,\n                profile_path,\n                markdown_path,\n                yaml_header,\n                args.overwrite_header_values,\n                sections_dict,\n                comma_sep_to_list(args.required_sections)\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Generation of the profile markdown failed')\n\n    def generate_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        profile_path: pathlib.Path,\n        markdown_path: pathlib.Path,\n        yaml_header: Dict[str, Any],\n        overwrite_header_values: bool,\n        sections_dict: Optional[Dict[str, str]],\n        required_sections: Optional[List[str]]\n    ) -> int:\n\"\"\"Generate markdown for the controls in the profile.\n\n        Args:\n            trestle_root: Root directory of the trestle workspace\n            profile_path: Path of the profile json file\n            markdown_path: Path to the directory into which the markdown will be written\n            yaml_header: Dict to merge into the yaml header of the control markdown\n            overwrite_header_values: Overwrite values in the markdown header but allow new items to be added\n            sections_dict: Optional dict mapping section short names to long\n            required_sections: Optional list of sections that get prompted for prose if not in the profile\n\n        Returns:\n            0 on success, 1 on error\n        \"\"\"\n        try:\n            if sections_dict and const.STATEMENT in sections_dict:\n                logger.warning('statement is not allowed as a section name.')\n                return CmdReturnCodes.COMMAND_ERROR.value\n            _, _, profile = ModelUtils.load_distributed(profile_path, trestle_root)\n            catalog, inherited_props = ProfileResolver().get_resolved_profile_catalog_and_inherited_props(\n                trestle_root, profile_path, True, True, None, ParameterRep.LEAVE_MOUSTACHE\n            )\n\n            deep_set(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.TITLE], profile.metadata.title)\n\n            context = ControlContext.generate(ContextPurpose.PROFILE, True, trestle_root, markdown_path)\n            context.cli_yaml_header = yaml_header\n            context.sections_dict = sections_dict\n            context.profile = profile\n            context.overwrite_header_values = overwrite_header_values\n            context.set_parameters_flag = True\n            context.required_sections = required_sections\n            context.inherited_props = inherited_props\n            catalog_api = CatalogAPI(catalog=catalog, context=context)\n            catalog_api.write_catalog_as_markdown()\n\n        except TrestleNotFoundError as e:\n            raise TrestleError(f'Profile {profile_path} not found, error {e}')\n        except TrestleError as e:\n            raise TrestleError(f'Error generating the catalog as markdown: {e}')\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileGenerate.generate_markdown","title":"generate_markdown(self, trestle_root, profile_path, markdown_path, yaml_header, overwrite_header_values, sections_dict, required_sections)","text":"

                                                                            Generate markdown for the controls in the profile.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            Root directory of the trestle workspace

                                                                            required profile_path Path

                                                                            Path of the profile json file

                                                                            required markdown_path Path

                                                                            Path to the directory into which the markdown will be written

                                                                            required yaml_header Dict[str, Any]

                                                                            Dict to merge into the yaml header of the control markdown

                                                                            required overwrite_header_values bool

                                                                            Overwrite values in the markdown header but allow new items to be added

                                                                            required sections_dict Optional[Dict[str, str]]

                                                                            Optional dict mapping section short names to long

                                                                            required required_sections Optional[List[str]]

                                                                            Optional list of sections that get prompted for prose if not in the profile

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success, 1 on error

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            def generate_markdown(\n    self,\n    trestle_root: pathlib.Path,\n    profile_path: pathlib.Path,\n    markdown_path: pathlib.Path,\n    yaml_header: Dict[str, Any],\n    overwrite_header_values: bool,\n    sections_dict: Optional[Dict[str, str]],\n    required_sections: Optional[List[str]]\n) -> int:\n\"\"\"Generate markdown for the controls in the profile.\n\n    Args:\n        trestle_root: Root directory of the trestle workspace\n        profile_path: Path of the profile json file\n        markdown_path: Path to the directory into which the markdown will be written\n        yaml_header: Dict to merge into the yaml header of the control markdown\n        overwrite_header_values: Overwrite values in the markdown header but allow new items to be added\n        sections_dict: Optional dict mapping section short names to long\n        required_sections: Optional list of sections that get prompted for prose if not in the profile\n\n    Returns:\n        0 on success, 1 on error\n    \"\"\"\n    try:\n        if sections_dict and const.STATEMENT in sections_dict:\n            logger.warning('statement is not allowed as a section name.')\n            return CmdReturnCodes.COMMAND_ERROR.value\n        _, _, profile = ModelUtils.load_distributed(profile_path, trestle_root)\n        catalog, inherited_props = ProfileResolver().get_resolved_profile_catalog_and_inherited_props(\n            trestle_root, profile_path, True, True, None, ParameterRep.LEAVE_MOUSTACHE\n        )\n\n        deep_set(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.PROFILE, const.TITLE], profile.metadata.title)\n\n        context = ControlContext.generate(ContextPurpose.PROFILE, True, trestle_root, markdown_path)\n        context.cli_yaml_header = yaml_header\n        context.sections_dict = sections_dict\n        context.profile = profile\n        context.overwrite_header_values = overwrite_header_values\n        context.set_parameters_flag = True\n        context.required_sections = required_sections\n        context.inherited_props = inherited_props\n        catalog_api = CatalogAPI(catalog=catalog, context=context)\n        catalog_api.write_catalog_as_markdown()\n\n    except TrestleNotFoundError as e:\n        raise TrestleError(f'Profile {profile_path} not found, error {e}')\n    except TrestleError as e:\n        raise TrestleError(f'Error generating the catalog as markdown: {e}')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit","title":" ProfileInherit (AuthorCommonCommand) ","text":"

                                                                            Generate and populate profile in JSON from a parent profile and leveraged ssp in the trestle workspace.

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            class ProfileInherit(AuthorCommonCommand):\n\"\"\"Generate and populate profile in JSON from a parent profile and leveraged ssp in the trestle workspace.\"\"\"\n\n    name = 'profile-inherit'\n\n    def _init_arguments(self) -> None:\n        ssp_help_str = 'Name of the leveraged ssp model in the trestle workspace'\n        self.add_argument('-s', '--ssp', help=ssp_help_str, required=True, type=str)\n        profile_help_str = 'Name of the parent profile model in the trestle workspace'\n        self.add_argument('-p', '--profile', help=profile_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json Profile'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root: pathlib.Path = args.trestle_root\n\n            if args.profile and args.profile == args.output:\n                logger.warning(f'Output profile {args.output} cannot equal parent')\n                return CmdReturnCodes.INCORRECT_ARGS.value\n\n            return self.initialize_profile(\n                trestle_root=trestle_root,\n                parent_prof_name=args.profile,\n                output_prof_name=args.output,\n                leveraged_ssp_name=args.ssp,\n                version=args.version\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Profile generation failed')\n\n    @staticmethod\n    def _is_inherited(all_comps: List[ssp.ByComponent]) -> bool:\n        # Fail fast by checking for any non-compliant components.\n        # Must contain provided export statements, no responsibility\n        # statements, and be implemented.\n        for comp in all_comps:\n            if comp.export is None:\n                return False\n\n            if comp.export.responsibilities is not None:\n                return False\n\n            if comp.export.provided is None:\n                return False\n\n            if comp.implementation_status.state != const.STATUS_IMPLEMENTED:\n                return False\n\n        return True\n\n    @staticmethod\n    def _create_components_by_id(leveraged_ssp: ssp.SystemSecurityPlan) -> Dict[str, List[ssp.ByComponent]]:\n        components_by_id: Dict[str, List[ssp.ByComponent]] = {}\n        for implemented_requirement in leveraged_ssp.control_implementation.implemented_requirements:\n            by_components: List[ssp.ByComponent] = []\n            if implemented_requirement.by_components:\n                by_components.extend(implemented_requirement.by_components)\n            if implemented_requirement.statements:\n                for stm in implemented_requirement.statements:\n                    if stm.by_components:\n                        by_components.extend(stm.by_components)\n            components_by_id[implemented_requirement.control_id] = none_if_empty(by_components)\n        return components_by_id\n\n    @staticmethod\n    def update_profile_import(\n        orig_prof_import: prof.Import, leveraged_ssp: ssp.SystemSecurityPlan, catalog_api: CatalogAPI\n    ) -> None:\n\"\"\"Add controls to different sections of a profile import based on catalog and leveraged SSP.\n\n        Args:\n            orig_prof_import: The original profile import that will have the control selection updated.\n            leveraged_ssp: SSP input for control filtering\n            catalog_api: Catalog API with access to controls that need to be filtered\n\n        Returns:\n            None\n        \"\"\"\n        exclude_with_ids: Set[str] = set()\n\n        # Create dictionary containing all by-components by control for faster searching\n        components_by_id: Dict[str, List[ssp.ByComponent]] = ProfileInherit._create_components_by_id(leveraged_ssp)\n\n        # Looping by controls in the catalog because the ids in the profile should\n        # be a subset of the catalog and not the ssp controls.\n        catalog_control_ids: Set[str] = set(catalog_api._catalog_interface.get_control_ids())\n        for control_id in catalog_control_ids:\n\n            if control_id not in components_by_id:\n                continue\n\n            by_comps: Optional[List[ssp.ByComponent]] = components_by_id[control_id]\n            if by_comps is not None and ProfileInherit._is_inherited(by_comps):\n                exclude_with_ids.add(control_id)\n\n        include_with_ids: Set[str] = catalog_control_ids - exclude_with_ids\n\n        orig_prof_import.include_controls = [prof.SelectControl(with_ids=sorted(include_with_ids))]\n        orig_prof_import.exclude_controls = [prof.SelectControl(with_ids=sorted(exclude_with_ids))]\n\n    def initialize_profile(\n        self,\n        trestle_root: pathlib.Path,\n        parent_prof_name: str,\n        output_prof_name: str,\n        leveraged_ssp_name: str,\n        version: Optional[str],\n    ) -> int:\n\"\"\"Initialize profile with controls from a parent profile, filtering by inherited controls.\n\n        Args:\n            trestle_root: Root directory of the trestle workspace\n            parent_prof_name: Name of the parent profile in the trestle workspace\n            output_prof_name: Name of the output profile json file\n            leveraged_ssp_name: Name of the ssp in the trestle workspace for control filtering\n            version: Optional profile version\n\n        Returns:\n            0 on success, 1 on error\n\n        Notes:\n            The profile model will either be updated or a new json profile created. This will overwrite\n            any import information on an exiting profile, but will preserve control modifications and parameters.\n            Allowing profile updates ensure that SSP export updates can be incorporated into an existing profile. All\n            controls from the original profile will exists and will be grouped by included and excluded controls based\n            on inheritance information.\n        \"\"\"\n        try:\n            result_profile: prof.Profile\n            existing_profile: Optional[prof.Profile] = None\n\n            existing_profile_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, output_prof_name, prof.Profile\n            )\n\n            # If a profile exists at the output path, use that as a starting point for a new profile.\n            # else create a new sample profile.\n            if existing_profile_path is not None:\n                existing_profile, _ = load_validate_model_name(trestle_root,\n                                                               output_prof_name,\n                                                               prof.Profile,\n                                                               FileContentType.JSON)\n                result_profile = copy.deepcopy(existing_profile)\n            else:\n                result_profile = gens.generate_sample_model(prof.Profile)\n\n            parent_prof_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, parent_prof_name, prof.Profile\n            )\n            if parent_prof_path is None:\n                raise TrestleNotFoundError(\n                    f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.'\n                )\n\n            local_path = f'profiles/{parent_prof_name}/profile.json'\n            profile_import: prof.Import = gens.generate_sample_model(prof.Import)\n            profile_import.href = const.TRESTLE_HREF_HEADING + local_path\n\n            leveraged_ssp: ssp.SystemSecurityPlan\n            try:\n                leveraged_ssp, _ = load_validate_model_name(\n                    trestle_root,\n                    leveraged_ssp_name,\n                    ssp.SystemSecurityPlan,\n                    FileContentType.JSON\n                )\n            except TrestleNotFoundError as e:\n                raise TrestleError(f'SSP {leveraged_ssp_name} not found: {e}')\n\n            prof_resolver = ProfileResolver()\n            catalog = prof_resolver.get_resolved_profile_catalog(\n                trestle_root, parent_prof_path, show_value_warnings=True\n            )\n            catalog_api = CatalogAPI(catalog=catalog)\n\n            # Sort controls based on what controls in the SSP have exported provided information with no\n            # customer responsibility\n            ProfileInherit.update_profile_import(profile_import, leveraged_ssp, catalog_api)\n\n            result_profile.imports[0] = profile_import\n\n            if version:\n                result_profile.metadata.version = version\n\n            if ModelUtils.models_are_equivalent(existing_profile, result_profile):\n                logger.info('Profile is no different from existing version, so no update.')\n                return CmdReturnCodes.SUCCESS.value\n\n            ModelUtils.update_last_modified(result_profile)\n            ModelUtils.save_top_level_model(result_profile, trestle_root, output_prof_name, FileContentType.JSON)\n\n        except TrestleError as e:\n            raise TrestleError(f'Error initializing profile {output_prof_name}: {e}')\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit.initialize_profile","title":"initialize_profile(self, trestle_root, parent_prof_name, output_prof_name, leveraged_ssp_name, version)","text":"

                                                                            Initialize profile with controls from a parent profile, filtering by inherited controls.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            Root directory of the trestle workspace

                                                                            required parent_prof_name str

                                                                            Name of the parent profile in the trestle workspace

                                                                            required output_prof_name str

                                                                            Name of the output profile json file

                                                                            required leveraged_ssp_name str

                                                                            Name of the ssp in the trestle workspace for control filtering

                                                                            required version Optional[str]

                                                                            Optional profile version

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success, 1 on error

                                                                            Notes

                                                                            The profile model will either be updated or a new json profile created. This will overwrite any import information on an exiting profile, but will preserve control modifications and parameters. Allowing profile updates ensure that SSP export updates can be incorporated into an existing profile. All controls from the original profile will exists and will be grouped by included and excluded controls based on inheritance information.

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            def initialize_profile(\n    self,\n    trestle_root: pathlib.Path,\n    parent_prof_name: str,\n    output_prof_name: str,\n    leveraged_ssp_name: str,\n    version: Optional[str],\n) -> int:\n\"\"\"Initialize profile with controls from a parent profile, filtering by inherited controls.\n\n    Args:\n        trestle_root: Root directory of the trestle workspace\n        parent_prof_name: Name of the parent profile in the trestle workspace\n        output_prof_name: Name of the output profile json file\n        leveraged_ssp_name: Name of the ssp in the trestle workspace for control filtering\n        version: Optional profile version\n\n    Returns:\n        0 on success, 1 on error\n\n    Notes:\n        The profile model will either be updated or a new json profile created. This will overwrite\n        any import information on an exiting profile, but will preserve control modifications and parameters.\n        Allowing profile updates ensure that SSP export updates can be incorporated into an existing profile. All\n        controls from the original profile will exists and will be grouped by included and excluded controls based\n        on inheritance information.\n    \"\"\"\n    try:\n        result_profile: prof.Profile\n        existing_profile: Optional[prof.Profile] = None\n\n        existing_profile_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, output_prof_name, prof.Profile\n        )\n\n        # If a profile exists at the output path, use that as a starting point for a new profile.\n        # else create a new sample profile.\n        if existing_profile_path is not None:\n            existing_profile, _ = load_validate_model_name(trestle_root,\n                                                           output_prof_name,\n                                                           prof.Profile,\n                                                           FileContentType.JSON)\n            result_profile = copy.deepcopy(existing_profile)\n        else:\n            result_profile = gens.generate_sample_model(prof.Profile)\n\n        parent_prof_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, parent_prof_name, prof.Profile\n        )\n        if parent_prof_path is None:\n            raise TrestleNotFoundError(\n                f'Profile {parent_prof_name} does not exist.  An existing profile must be provided.'\n            )\n\n        local_path = f'profiles/{parent_prof_name}/profile.json'\n        profile_import: prof.Import = gens.generate_sample_model(prof.Import)\n        profile_import.href = const.TRESTLE_HREF_HEADING + local_path\n\n        leveraged_ssp: ssp.SystemSecurityPlan\n        try:\n            leveraged_ssp, _ = load_validate_model_name(\n                trestle_root,\n                leveraged_ssp_name,\n                ssp.SystemSecurityPlan,\n                FileContentType.JSON\n            )\n        except TrestleNotFoundError as e:\n            raise TrestleError(f'SSP {leveraged_ssp_name} not found: {e}')\n\n        prof_resolver = ProfileResolver()\n        catalog = prof_resolver.get_resolved_profile_catalog(\n            trestle_root, parent_prof_path, show_value_warnings=True\n        )\n        catalog_api = CatalogAPI(catalog=catalog)\n\n        # Sort controls based on what controls in the SSP have exported provided information with no\n        # customer responsibility\n        ProfileInherit.update_profile_import(profile_import, leveraged_ssp, catalog_api)\n\n        result_profile.imports[0] = profile_import\n\n        if version:\n            result_profile.metadata.version = version\n\n        if ModelUtils.models_are_equivalent(existing_profile, result_profile):\n            logger.info('Profile is no different from existing version, so no update.')\n            return CmdReturnCodes.SUCCESS.value\n\n        ModelUtils.update_last_modified(result_profile)\n        ModelUtils.save_top_level_model(result_profile, trestle_root, output_prof_name, FileContentType.JSON)\n\n    except TrestleError as e:\n        raise TrestleError(f'Error initializing profile {output_prof_name}: {e}')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileInherit.update_profile_import","title":"update_profile_import(orig_prof_import, leveraged_ssp, catalog_api) staticmethod","text":"

                                                                            Add controls to different sections of a profile import based on catalog and leveraged SSP.

                                                                            Parameters:

                                                                            Name Type Description Default orig_prof_import Import

                                                                            The original profile import that will have the control selection updated.

                                                                            required leveraged_ssp SystemSecurityPlan

                                                                            SSP input for control filtering

                                                                            required catalog_api CatalogAPI

                                                                            Catalog API with access to controls that need to be filtered

                                                                            required

                                                                            Returns:

                                                                            Type Description None

                                                                            None

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            @staticmethod\ndef update_profile_import(\n    orig_prof_import: prof.Import, leveraged_ssp: ssp.SystemSecurityPlan, catalog_api: CatalogAPI\n) -> None:\n\"\"\"Add controls to different sections of a profile import based on catalog and leveraged SSP.\n\n    Args:\n        orig_prof_import: The original profile import that will have the control selection updated.\n        leveraged_ssp: SSP input for control filtering\n        catalog_api: Catalog API with access to controls that need to be filtered\n\n    Returns:\n        None\n    \"\"\"\n    exclude_with_ids: Set[str] = set()\n\n    # Create dictionary containing all by-components by control for faster searching\n    components_by_id: Dict[str, List[ssp.ByComponent]] = ProfileInherit._create_components_by_id(leveraged_ssp)\n\n    # Looping by controls in the catalog because the ids in the profile should\n    # be a subset of the catalog and not the ssp controls.\n    catalog_control_ids: Set[str] = set(catalog_api._catalog_interface.get_control_ids())\n    for control_id in catalog_control_ids:\n\n        if control_id not in components_by_id:\n            continue\n\n        by_comps: Optional[List[ssp.ByComponent]] = components_by_id[control_id]\n        if by_comps is not None and ProfileInherit._is_inherited(by_comps):\n            exclude_with_ids.add(control_id)\n\n    include_with_ids: Set[str] = catalog_control_ids - exclude_with_ids\n\n    orig_prof_import.include_controls = [prof.SelectControl(with_ids=sorted(include_with_ids))]\n    orig_prof_import.exclude_controls = [prof.SelectControl(with_ids=sorted(exclude_with_ids))]\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve","title":" ProfileResolve (AuthorCommonCommand) ","text":"

                                                                            Resolve profile to resolved profile catalog.

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            class ProfileResolve(AuthorCommonCommand):\n\"\"\"Resolve profile to resolved profile catalog.\"\"\"\n\n    name = 'profile-resolve'\n\n    def _init_arguments(self) -> None:\n        name_help_str = 'Name of the source profile model in the trestle workspace'\n        self.add_argument('-n', '--name', help=name_help_str, required=True, type=str)\n        self.add_argument('-o', '--output', help='Name of the output resolved profile catalog', required=True, type=str)\n        self.add_argument(\n            '-sv',\n            '--show-values',\n            help='Show values for parameters in prose',\n            required=False,\n            action='store_true',\n            default=False\n        )\n        self.add_argument(\n            '-sl',\n            '--show-labels',\n            help='Show labels for parameters in prose instead of values',\n            required=False,\n            action='store_true',\n            default=False\n        )\n        self.add_argument(\n            '-bf',\n            '--bracket-format',\n            help='With -sv, allows brackets around value, e.g. [.] or ((.)), with the dot representing the value.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-vap',\n            '--value-assigned-prefix',\n            help='With -sv, places a prefix in front of the parameter string if a value has been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-vnap',\n            '--value-not-assigned-prefix',\n            help='With -sv, places a prefix in front of the parameter string if a value has *not* been assigned.',\n            required=False,\n            type=str,\n            default=''\n        )\n        self.add_argument(\n            '-lp',\n            '--label-prefix',\n            help='With -sl, places a prefix in front of the parameter label.',\n            required=False,\n            type=str,\n            default=''\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root: pathlib.Path = args.trestle_root\n            profile_path = trestle_root / f'profiles/{args.name}/profile.json'\n            catalog_name = args.output\n            show_values = args.show_values\n            param_format = args.bracket_format\n            value_assigned_prefix = args.value_assigned_prefix\n            value_not_assigned_prefix = args.value_not_assigned_prefix\n            label_prefix = args.label_prefix\n            show_labels = args.show_labels\n\n            return self.resolve_profile(\n                trestle_root,\n                profile_path,\n                catalog_name,\n                show_values,\n                param_format,\n                value_assigned_prefix,\n                value_not_assigned_prefix,\n                show_labels,\n                label_prefix\n            )\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Generation of the resolved profile catalog failed')\n\n    def resolve_profile(\n        self,\n        trestle_root: pathlib.Path,\n        profile_path: pathlib.Path,\n        catalog_name: str,\n        show_values: bool,\n        bracket_format: str,\n        value_assigned_prefix: Optional[str],\n        value_not_assigned_prefix: Optional[str],\n        show_labels: bool,\n        label_prefix: Optional[str]\n    ) -> int:\n\"\"\"Create resolved profile catalog from given profile.\n\n        Args:\n            trestle_root: Root directory of the trestle workspace\n            profile_path: Path of the profile json file\n            catalog_name: Name of the resolved profile catalog\n            show_values: If true, show values of parameters in prose rather than original {{}} form\n            bracket_format: String representing brackets around value, e.g. [.] or ((.))\n            value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n            value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n            show_labels: Show labels for parameters and not values\n            label_prefix: Prefix placed in front of param label\n\n        Returns:\n            0 on success and raises exception on error\n        \"\"\"\n        if not profile_path.exists():\n            raise TrestleNotFoundError(f'Cannot resolve profile catalog: profile {profile_path} does not exist.')\n\n        param_rep = ParameterRep.LEAVE_MOUSTACHE\n        if show_values:\n            param_rep = ParameterRep.ASSIGNMENT_FORM\n            if label_prefix or show_labels:\n                raise TrestleError('Use of show-values is not compatible with show-labels or label-prefix')\n        elif value_assigned_prefix or value_not_assigned_prefix:\n            raise TrestleError('Use of value-assigned-prefix or value-not-assigned-prefix requires show-values')\n        if show_labels:\n            param_rep = ParameterRep.LABEL_FORM\n            # overload value_not_assigned_prefix to use the label_prefix value\n            value_not_assigned_prefix = label_prefix\n        elif label_prefix:\n            raise TrestleError('Use of label-prefix requires show-labels')\n\n        bracket_format = none_if_empty(bracket_format)\n        catalog = ProfileResolver().get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            False,\n            False,\n            bracket_format,\n            param_rep,\n            False,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        ModelUtils.save_top_level_model(catalog, trestle_root, catalog_name, FileContentType.JSON)\n\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.prof/#trestle.core.commands.author.prof.ProfileResolve.resolve_profile","title":"resolve_profile(self, trestle_root, profile_path, catalog_name, show_values, bracket_format, value_assigned_prefix, value_not_assigned_prefix, show_labels, label_prefix)","text":"

                                                                            Create resolved profile catalog from given profile.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            Root directory of the trestle workspace

                                                                            required profile_path Path

                                                                            Path of the profile json file

                                                                            required catalog_name str

                                                                            Name of the resolved profile catalog

                                                                            required show_values bool

                                                                            If true, show values of parameters in prose rather than original {{}} form

                                                                            required bracket_format str

                                                                            String representing brackets around value, e.g. [.] or ((.))

                                                                            required value_assigned_prefix Optional[str]

                                                                            Prefix placed in front of param string if a value was assigned

                                                                            required value_not_assigned_prefix Optional[str]

                                                                            Prefix placed in front of param string if a value was not assigned

                                                                            required show_labels bool

                                                                            Show labels for parameters and not values

                                                                            required label_prefix Optional[str]

                                                                            Prefix placed in front of param label

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success and raises exception on error

                                                                            Source code in trestle/core/commands/author/prof.py
                                                                            def resolve_profile(\n    self,\n    trestle_root: pathlib.Path,\n    profile_path: pathlib.Path,\n    catalog_name: str,\n    show_values: bool,\n    bracket_format: str,\n    value_assigned_prefix: Optional[str],\n    value_not_assigned_prefix: Optional[str],\n    show_labels: bool,\n    label_prefix: Optional[str]\n) -> int:\n\"\"\"Create resolved profile catalog from given profile.\n\n    Args:\n        trestle_root: Root directory of the trestle workspace\n        profile_path: Path of the profile json file\n        catalog_name: Name of the resolved profile catalog\n        show_values: If true, show values of parameters in prose rather than original {{}} form\n        bracket_format: String representing brackets around value, e.g. [.] or ((.))\n        value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n        value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n        show_labels: Show labels for parameters and not values\n        label_prefix: Prefix placed in front of param label\n\n    Returns:\n        0 on success and raises exception on error\n    \"\"\"\n    if not profile_path.exists():\n        raise TrestleNotFoundError(f'Cannot resolve profile catalog: profile {profile_path} does not exist.')\n\n    param_rep = ParameterRep.LEAVE_MOUSTACHE\n    if show_values:\n        param_rep = ParameterRep.ASSIGNMENT_FORM\n        if label_prefix or show_labels:\n            raise TrestleError('Use of show-values is not compatible with show-labels or label-prefix')\n    elif value_assigned_prefix or value_not_assigned_prefix:\n        raise TrestleError('Use of value-assigned-prefix or value-not-assigned-prefix requires show-values')\n    if show_labels:\n        param_rep = ParameterRep.LABEL_FORM\n        # overload value_not_assigned_prefix to use the label_prefix value\n        value_not_assigned_prefix = label_prefix\n    elif label_prefix:\n        raise TrestleError('Use of label-prefix requires show-labels')\n\n    bracket_format = none_if_empty(bracket_format)\n    catalog = ProfileResolver().get_resolved_profile_catalog(\n        trestle_root,\n        profile_path,\n        False,\n        False,\n        bracket_format,\n        param_rep,\n        False,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    ModelUtils.save_top_level_model(catalog, trestle_root, catalog_name, FileContentType.JSON)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.ssp/","title":"ssp","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp","title":"trestle.core.commands.author.ssp","text":"

                                                                            Create ssp from catalog and profile.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPAssemble","title":" SSPAssemble (AuthorCommonCommand) ","text":"

                                                                            Assemble markdown files of controls into an SSP json file.

                                                                            Source code in trestle/core/commands/author/ssp.py
                                                                            class SSPAssemble(AuthorCommonCommand):\n\"\"\"Assemble markdown files of controls into an SSP json file.\"\"\"\n\n    name = 'ssp-assemble'\n\n    def _init_arguments(self) -> None:\n        name_help_str = (\n            'Optional name of the ssp model in the trestle workspace that is being modified.  '\n            'If not provided the output name is used.'\n        )\n        self.add_argument('-n', '--name', help=name_help_str, required=False, type=str)\n        file_help_str = 'Name of the input markdown file directory'\n        self.add_argument('-m', '--markdown', help=file_help_str, required=True, type=str)\n        output_help_str = 'Name of the output generated json SSP'\n        self.add_argument('-cd', '--compdefs', help=const.HELP_COMPDEFS, required=False, type=str)\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n\n    @staticmethod\n    def _get_ssp_component(ssp: ossp.SystemSecurityPlan, gen_comp: generic.GenericComponent) -> ossp.SystemComponent:\n        for component in as_list(ssp.system_implementation.components):\n            if component.title == gen_comp.title:\n                return component\n        # if this is a new system component assign its status as operational by default\n        # the status of the system components are not stored in the markdown\n        gen_comp.status.state = const.STATUS_OPERATIONAL\n        new_component = gen_comp.as_system_component()\n        return new_component\n\n    @staticmethod\n    def _merge_by_comps(stat: ossp.Statement, statement: ossp.Statement, set_params: List[ossp.SetParameter]) -> None:\n        for by_comp in as_list(statement.by_components):\n            found = False\n            for dest_by_comp in as_list(stat.by_components):\n                if dest_by_comp.component_uuid == by_comp.component_uuid:\n                    dest_by_comp.description = by_comp.description\n                    dest_by_comp.props = as_list(dest_by_comp.props)\n                    dest_by_comp.props.extend(as_list(statement.props))\n                    dest_by_comp.props = none_if_empty(ControlInterface.clean_props(by_comp.props))\n                    dest_by_comp.implementation_status = by_comp.implementation_status\n                    dest_by_comp.set_parameters = none_if_empty(set_params)\n                    found = True\n                    break\n            if not found:\n                stat.by_components = as_list(stat.by_components)\n                by_comp.set_parameters = none_if_empty(set_params)\n                stat.by_components.append(by_comp)\n\n    @staticmethod\n    def _merge_statement(\n        imp_req: ossp.ImplementedRequirement,\n        statement: generic.GenericStatement,\n        set_params: List[ossp.SetParameter],\n    ) -> None:\n\"\"\"Merge the generic statement into the statements of the imp_req.\"\"\"\n        # if the statement id is already in the imp_req, merge its by_comps into the existing statement\n        for stat in as_list(imp_req.statements):\n            if stat.statement_id == statement.statement_id:\n                SSPAssemble._merge_by_comps(stat, statement, set_params)\n                return\n        # otherwise just ad the statement - but only if it has by_comps\n        if statement.by_components:\n            imp_req.statements = as_list(imp_req.statements)\n            imp_req.statements.append(statement)\n\n    @staticmethod\n    def _merge_imp_req_into_imp_req(\n        imp_req: ossp.ImplementedRequirement,\n        gen_imp_req: generic.GenericImplementedRequirement,\n        set_params: List[ossp.SetParameter]\n    ) -> None:\n\"\"\"Merge comp def imp req into existing imp req.\"\"\"\n        # convert generic imp req from comp defs into ssp form\n        src_imp_req = gen_imp_req.as_ssp()\n        imp_req.props = none_if_empty(\n            ControlInterface.clean_props(gen_imp_req.props, remove_imp_status=True, remove_all_rule_info=True)\n        )\n        for statement in as_list(src_imp_req.statements):\n            SSPAssemble._merge_statement(imp_req, statement, set_params)\n\n    @staticmethod\n    def _get_params_for_rules(context: ControlContext, rules_list: List[str],\n                              set_params: List[ossp.SetParameter]) -> List[ossp.SetParameter]:\n\"\"\"Get all set_params needed by the rules along with non-rule set_params.\"\"\"\n        needed_param_ids: Set[str] = set()\n        rule_dict = context.rules_params_dict.get(context.comp_name, {})\n        # find param_ids needed by rules\n        for rule_id in rules_list:\n            # get list of param_ids associated with this rule_id\n            param_ids = [\n                param['name'] for params in rule_dict.values() for param in params if param['rule-id'] == rule_id\n            ]\n            needed_param_ids.update(param_ids)\n        all_rule_param_ids = [param['name'] for params in rule_dict.values() for param in params]\n        # any set_param that isn't associated with a rule should be included as a normal control set param with no rule\n        for set_param in set_params:\n            if set_param.param_id not in all_rule_param_ids:\n                needed_param_ids.add(set_param.param_id)\n        param_ids_list = sorted(needed_param_ids)\n        needed_set_params: List[ossp.SetParameter] = []\n        for param_id in param_ids_list:\n            set_param = None\n            for sp in set_params:\n                if sp.param_id == param_id:\n                    set_param = sp\n                    break\n            if set_param:\n                needed_set_params.append(set_param)\n            else:\n                logger.warning(f'No set param found for param {param_id}')\n        return needed_set_params\n\n    @staticmethod\n    def _add_imp_req_to_ssp(\n        ssp: ossp.SystemSecurityPlan,\n        gen_comp: generic.GenericComponent,\n        gen_imp_req: generic.GenericImplementedRequirement,\n        set_params: List[ossp.SetParameter],\n        context: ControlContext\n    ) -> None:\n\"\"\"Add imp req from control implementation into new ssp being assembled.\"\"\"\n        # the incoming gen_imp_req comes directly from the comp def\n        # but the imp_req here is pulled from the ssp and created if not already there\n        imp_req = CatalogReader._get_imp_req_for_control(ssp, gen_imp_req.control_id)\n        local_set_params = as_list(set_params)[:]\n        local_set_params.extend(as_list(imp_req.set_parameters))\n        local_set_params = ControlInterface.uniquify_set_params(local_set_params)\n        # get any rules set at control level, if present\n        rules_list, _ = ControlInterface.get_rule_list_for_item(gen_imp_req)  # type: ignore\n        # There should be no rule content at top level of imp_req in ssp so strip them out\n        imp_req.props = none_if_empty(\n            ControlInterface.clean_props(gen_imp_req.props, remove_imp_status=True, remove_all_rule_info=True)\n        )\n        # if we have rules applying or need to make set_params, we need to make a by_comp\n        control_set_params = SSPAssemble._get_params_for_rules(context, rules_list, local_set_params)\n        if rules_list or control_set_params:\n            by_comp = gens.generate_sample_model(ossp.ByComponent)\n            by_comp.component_uuid = gen_comp.uuid\n            by_comp.description = gen_imp_req.description\n            by_comp.set_parameters = none_if_empty(control_set_params)\n            by_comp.implementation_status = ControlInterface.get_status_from_props(gen_imp_req)  # type: ignore\n            by_comp.props = none_if_empty(ControlInterface.clean_props(gen_imp_req.props))\n            imp_req.by_components = as_list(imp_req.by_components)\n            imp_req.by_components.append(by_comp)\n        # each statement in ci corresponds to by_comp in an ssp imp req\n        # so insert the new by_comp directly into the ssp, generating parts as needed\n        imp_req.statements = as_list(imp_req.statements)\n        for statement in as_list(gen_imp_req.statements):\n            if ControlInterface.item_has_rules(statement):  # type: ignore\n                imp_req = CatalogReader._get_imp_req_for_statement(ssp, gen_imp_req.control_id, statement.statement_id)\n                by_comp = CatalogReader._get_by_comp_from_imp_req(imp_req, statement.statement_id, gen_comp.uuid)\n                by_comp.description = statement.description\n                by_comp.props = none_if_empty(ControlInterface.clean_props(statement.props))\n                rules_list, _ = ControlInterface.get_rule_list_for_item(statement)  # type: ignore\n                by_comp.set_parameters = none_if_empty(\n                    SSPAssemble._get_params_for_rules(context, rules_list, local_set_params)\n                )\n        imp_req.statements = none_if_empty(imp_req.statements)\n        ssp.control_implementation.implemented_requirements = as_list(\n            ssp.control_implementation.implemented_requirements\n        )\n\n    @staticmethod\n    def _merge_imp_req_into_ssp(\n        ssp: ossp.SystemSecurityPlan,\n        gen_imp_req: generic.GenericImplementedRequirement,\n        set_params: List[ossp.SetParameter],\n    ) -> None:\n\"\"\"Merge the new imp_reqs into the ssp.\"\"\"\n        for imp_req in as_list(ssp.control_implementation.implemented_requirements):\n            if imp_req.control_id == gen_imp_req.control_id:\n                SSPAssemble._merge_imp_req_into_imp_req(imp_req, gen_imp_req, set_params)\n                return\n        new_imp_req = gen_imp_req.as_ssp()\n        imp_req.props = none_if_empty(\n            ControlInterface.clean_props(gen_imp_req.props, remove_imp_status=True, remove_all_rule_info=True)\n        )\n        ssp.control_implementation.implemented_requirements.append(new_imp_req)\n\n    def _merge_comp_defs(\n        self,\n        ssp: ossp.SystemSecurityPlan,\n        comp_dict: Dict[str, generic.GenericComponent],\n        context: ControlContext,\n        catalog_interface: CatalogInterface\n    ) -> None:\n\"\"\"Merge the original generic comp defs into the ssp.\"\"\"\n        all_comps: List[ossp.SystemComponent] = []\n        # determine if this is a new and empty ssp\n        new_ssp = not ssp.control_implementation.implemented_requirements\n        for _, gen_comp in comp_dict.items():\n            context.comp_name = gen_comp.title\n            all_ci_props: List[com.Property] = []\n            ssp_comp = SSPAssemble._get_ssp_component(ssp, gen_comp)\n            set_params: List[ossp.SetParameter] = []\n            for ci in as_list(gen_comp.control_implementations):\n                all_ci_props.extend(as_list(ci.props))\n                # get the list of set_params in the control implementation - for this component\n                for sp in as_list(ci.set_parameters):\n                    set_params.append(sp.to_ssp())\n                for imp_req in as_list(ci.implemented_requirements):\n                    # ignore any controls not in the ssp profile (resolved catalog)\n                    if not catalog_interface.get_control(imp_req.control_id):\n                        logger.debug(f'Ignoring imp_req for control {imp_req.control_id} not in ssp profile')\n                        continue\n                    if new_ssp:\n                        SSPAssemble._add_imp_req_to_ssp(ssp, gen_comp, imp_req, set_params, context)\n                    else:\n                        # compile all new uuids for new component definitions\n                        comp_uuids = [x.uuid for x in comp_dict.values()]\n                        for imp_requirement in as_list(ssp.control_implementation.implemented_requirements):\n                            to_delete = []\n                            for i, by_comp in enumerate(imp_requirement.by_components):\n                                if by_comp.component_uuid not in comp_uuids:\n                                    logger.warning(\n                                        f'By_component {by_comp.component_uuid} removed from implemented requirement '\n                                        f'{imp_requirement.control_id} because the corresponding component is not in '\n                                        'the specified compdefs '\n                                    )\n                                    to_delete.append(i)\n                            if to_delete:\n                                delete_list_from_list(imp_requirement.by_components, to_delete)\n                        SSPAssemble._merge_imp_req_into_ssp(ssp, imp_req, set_params)\n            ssp_comp.props = as_list(gen_comp.props)\n            ssp_comp.props.extend(all_ci_props)\n            ssp_comp.props = none_if_empty(ControlInterface.clean_props(ssp_comp.props))\n            all_comps.append(ssp_comp)\n\n        ssp.system_implementation.components = none_if_empty(all_comps)\n\n    def _generate_roles_in_metadata(self, ssp: ossp.SystemSecurityPlan) -> bool:\n\"\"\"Find all roles referenced by imp reqs and create role in metadata as needed.\"\"\"\n        metadata = ssp.metadata\n        metadata.roles = as_list(metadata.roles)\n        known_role_ids = [role.id for role in metadata.roles]\n        changed = False\n        for imp_req in ssp.control_implementation.implemented_requirements:\n            role_ids = [resp_role.role_id for resp_role in as_list(imp_req.responsible_roles)]\n            for role_id in role_ids:\n                if role_id not in known_role_ids:\n                    role = com.Role(id=role_id, title=role_id)\n                    metadata.roles.append(role)\n                    known_role_ids.append(role_id)\n                    changed = True\n        metadata.roles = none_if_empty(metadata.roles)\n        return changed\n\n    @staticmethod\n    def _build_comp_dict_from_comp_defs(\n        trestle_root: pathlib.Path, comp_def_name_list: List[str], create_sys_comp: bool\n    ) -> Dict[str, generic.GenericComponent]:\n        comp_dict: Dict[str, generic.GenericComponent] = {}\n        for comp_name in comp_def_name_list:\n            comp_def, _ = ModelUtils.load_model_for_class(trestle_root, comp_name, comp.ComponentDefinition)\n            for def_comp in as_list(comp_def.components):\n                gen_def_comp = generic.GenericComponent.from_defined_component(def_comp)\n                comp_dict[def_comp.title] = gen_def_comp\n        if create_sys_comp:\n            sys_comp = generic.GenericComponent.generate()\n            sys_comp.type = const.THIS_SYSTEM_AS_KEY\n            sys_comp.title = const.SSP_MAIN_COMP_NAME\n            comp_dict[sys_comp.title] = sys_comp\n        return comp_dict\n\n    @staticmethod\n    def _get_this_system_as_gen_comp(ssp: ossp.SystemSecurityPlan) -> Optional[generic.GenericComponent]:\n        for component in as_list(ssp.system_implementation.components):\n            if component.title == const.SSP_MAIN_COMP_NAME:\n                return generic.GenericComponent.from_defined_component(component)\n        return None\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n\n            md_path = trestle_root / args.markdown\n\n            # the original, reference ssp name defaults to same as output if name not specified\n            # thus in cyclic editing you are reading and writing same json ssp\n            orig_ssp_name = args.output\n            if args.name:\n                orig_ssp_name = args.name\n            new_ssp_name = args.output\n\n            _, profile_href = ComponentAssemble._get_profile_title_and_href_from_dir(md_path)\n            res_cat = ProfileResolver.get_resolved_profile_catalog(\n                trestle_root, profile_href, param_rep=ParameterRep.LEAVE_MOUSTACHE\n            )\n            catalog_interface = CatalogInterface(res_cat)\n\n            new_file_content_type = FileContentType.JSON\n\n            # if output ssp already exists, load it to see if new one is different\n            existing_ssp: Optional[ossp.SystemSecurityPlan] = None\n            new_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, new_ssp_name, ossp.SystemSecurityPlan\n            )\n            if new_ssp_path:\n                _, _, existing_ssp = ModelUtils.load_distributed(new_ssp_path, trestle_root)\n                new_file_content_type = FileContentType.path_to_content_type(new_ssp_path)\n\n            ssp: ossp.SystemSecurityPlan\n\n            # if orig ssp exists - need to load it rather than instantiate new one\n            orig_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n                trestle_root, orig_ssp_name, ossp.SystemSecurityPlan\n            )\n\n            context = ControlContext.generate(ContextPurpose.SSP, True, trestle_root, md_path)\n            context.comp_def_name_list = comma_sep_to_list(args.compdefs)\n            part_id_map_by_id = catalog_interface.get_statement_part_id_map(False)\n            catalog_interface.generate_control_rule_info(part_id_map_by_id, context)\n\n            # load all original comp defs\n            # only additions from markdown will be imp_req prose and status\n            # and param vals\n            # if this is a new ssp then create system component in the comp_dict\n            comp_dict = SSPAssemble._build_comp_dict_from_comp_defs(\n                trestle_root, context.comp_def_name_list, not orig_ssp_path\n            )\n\n            part_id_map_by_label = catalog_interface.get_statement_part_id_map(True)\n\n            # if ssp already exists use it as container for new content\n            if orig_ssp_path:\n                # load the existing json ssp\n                _, _, ssp = ModelUtils.load_distributed(orig_ssp_path, trestle_root)\n                # add the This System comp to the comp dict so its uuid is known\n                sys_comp = SSPAssemble._get_this_system_as_gen_comp(ssp)\n                if not sys_comp:\n                    raise TrestleError('Original ssp has no system component.')\n                comp_dict[const.SSP_MAIN_COMP_NAME] = sys_comp\n\n                ssp_sys_imp_comps = ssp.system_implementation.components\n                # Gather the leveraged components to add back after the merge\n                leveraged_comps: Dict[str, ossp.SystemComponent] = {}\n                for sys_comp in ssp_sys_imp_comps:\n                    if sys_comp.props is not None:\n                        prop_names = [x.name for x in sys_comp.props]\n                        if const.LEV_AUTH_UUID in prop_names:\n                            leveraged_comps[sys_comp.title] = sys_comp\n\n                # Verifies older compdefs in an ssp no longer exist in newly provided ones\n                comp_titles = [x.title for x in comp_dict.values()]\n                diffs = [x for x in ssp_sys_imp_comps if x.title not in comp_titles and x.title not in leveraged_comps]\n                if diffs:\n                    for diff in diffs:\n                        logger.warning(\n                            f'Component named: {diff.title} was removed from system components from ssp '\n                            'because the corresponding component is not in '\n                            'the specified compdefs '\n                        )\n                    index_list = [ssp_sys_imp_comps.index(value) for value in diffs if value in ssp_sys_imp_comps]\n                    delete_list_from_list(ssp.system_implementation.components, index_list)\n\n                self._merge_comp_defs(ssp, comp_dict, context, catalog_interface)\n                CatalogReader.read_ssp_md_content(md_path, ssp, comp_dict, part_id_map_by_label, context)\n\n                new_file_content_type = FileContentType.path_to_content_type(orig_ssp_path)\n\n                # Add the leveraged comps back to the final ssp\n                ssp.system_implementation.components.extend(list(leveraged_comps.values()))\n            else:\n                # create a sample ssp to hold all the parts\n                ssp = gens.generate_sample_model(ossp.SystemSecurityPlan)\n                ssp.control_implementation.implemented_requirements = []\n                ssp.control_implementation.description = const.SSP_SYSTEM_CONTROL_IMPLEMENTATION_TEXT\n                ssp.system_implementation.components = []\n                self._merge_comp_defs(ssp, comp_dict, context, catalog_interface)\n                CatalogReader.read_ssp_md_content(md_path, ssp, comp_dict, part_id_map_by_label, context)\n\n                import_profile: ossp.ImportProfile = gens.generate_sample_model(ossp.ImportProfile)\n                import_profile.href = const.REPLACE_ME\n                ssp.import_profile = import_profile\n\n            # now that we know the complete list of needed components, add them to the sys_imp\n            # TODO if the ssp already existed then components may need to be removed if not ref'd by imp_reqs\n            self._generate_roles_in_metadata(ssp)\n\n            # If this is a leveraging SSP, update it with the retrieved exports from the leveraged SSP\n            inheritance_markdown_path = md_path.joinpath(const.INHERITANCE_VIEW_DIR)\n            if os.path.exists(inheritance_markdown_path):\n                SSPInheritanceAPI(inheritance_markdown_path, trestle_root).update_ssp_inheritance(ssp)\n\n            ssp.import_profile.href = profile_href\n\n            if args.version:\n                ssp.metadata.version = args.version\n\n            if ModelUtils.models_are_equivalent(existing_ssp, ssp):\n                logger.info('No changes to assembled ssp so ssp not written out.')\n                return CmdReturnCodes.SUCCESS.value\n\n            if args.regenerate:\n                ssp, _, _ = ModelUtils.regenerate_uuids(ssp)\n            ModelUtils.update_last_modified(ssp)\n            # validate model rules before saving\n            args_validate = argparse.Namespace(mode=const.VAL_MODE_RULES)\n            validator: Validator = validator_factory.get(args_validate)\n            if not validator.model_is_valid(ssp, True, trestle_root):\n                logger.error(\n                    'Validation of file to be imported did not pass. Rule parameter values validation failed, '\n                    'please check values are correct for shared parameters in current model'\n                )\n                return CmdReturnCodes.COMMAND_ERROR.value\n            # write out the ssp as json\n            ModelUtils.save_top_level_model(ssp, trestle_root, new_ssp_name, new_file_content_type)\n\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while assembling SSP')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPAssemble.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter","title":" SSPFilter (AuthorCommonCommand) ","text":"

                                                                            Filter the controls in an ssp.

                                                                            The filtered ssp is based on controls included by the following: profile, components, implementation status, and/or control origination.

                                                                            Source code in trestle/core/commands/author/ssp.py
                                                                            class SSPFilter(AuthorCommonCommand):\n\"\"\"\n    Filter the controls in an ssp.\n\n    The filtered ssp is based on controls included by the following:\n    profile, components, implementation status, and/or control origination.\n    \"\"\"\n\n    name = 'ssp-filter'\n\n    def _init_arguments(self) -> None:\n        file_help_str = 'Name of the input ssp'\n        self.add_argument('-n', '--name', help=file_help_str, required=True, type=str)\n        file_help_str = 'Name of the optional input profile that defines set of controls in filtered ssp'\n        self.add_argument('-p', '--profile', help=file_help_str, required=False, type=str)\n        output_help_str = 'Name of the output generated SSP'\n        self.add_argument('-o', '--output', help=output_help_str, required=True, type=str)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n        self.add_argument('-vn', '--version', help=const.HELP_VERSION, required=False, type=str)\n        comp_help_str = 'Colon-delimited list of component names to include in filtered ssp.'\n        self.add_argument('-c', '--components', help=comp_help_str, required=False, type=str)\n        is_help_str = 'Comma-delimited list of control implementation statuses to include in filtered ssp.'\n        self.add_argument('-is', '--implementation-status', help=is_help_str, required=False, type=str)\n        co_help_str = 'Comma-delimited list of control origination values to include in filtered ssp.'\n        self.add_argument('-co', '--control-origination', help=co_help_str, required=False, type=str)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = pathlib.Path(args.trestle_root)\n            comp_names: Optional[List[str]] = None\n            impl_status_values: Optional[List[str]] = None\n            co_values: Optional[List[str]] = None\n\n            if not (args.components or args.implementation_status or args.profile or args.control_origination):\n                logger.warning(\n                    'You must specify at least one, or a combination of: profile, list of component names'\n                    ', list of implementation statuses, or list of control origination values for ssp-filter.'\n                )\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n            if args.components:\n                comp_names = args.components.split(':')\n\n            if args.implementation_status:\n                impl_status_values = args.implementation_status.split(',')\n                allowed_is_values = {\n                    const.STATUS_PLANNED,\n                    const.STATUS_PARTIAL,\n                    const.STATUS_IMPLEMENTED,\n                    const.STATUS_ALTERNATIVE,\n                    const.STATUS_NOT_APPLICABLE\n                }\n                allowed_is_string = ', '.join(str(item) for item in allowed_is_values)\n                for impl_status in impl_status_values:\n                    if impl_status not in allowed_is_values:\n                        logger.warning(\n                            f'Provided implementation status \"{impl_status}\" is invalid.\\n'\n                            f'Please use the following for ssp-filter: {allowed_is_string}'\n                        )\n                        return CmdReturnCodes.COMMAND_ERROR.value\n\n            if args.control_origination:\n                co_values = args.control_origination.split(',')\n                allowed_co_values = {\n                    const.ORIGINATION_ORGANIZATION,\n                    const.ORIGINATION_SYSTEM_SPECIFIC,\n                    const.ORIGINATION_INHERITED,\n                    const.ORIGINATION_CUSTOMER_CONFIGURED,\n                    const.ORIGINATION_CUSTOMER_PROVIDED\n                }\n                allowed_co_string = ', '.join(str(item) for item in allowed_co_values)\n                for co in co_values:\n                    if co not in allowed_co_values:\n                        logger.warning(\n                            f'Provided control origination \"{co}\" is invalid.\\n'\n                            f'Please use the following for ssp-filter: {allowed_co_string}'\n                        )\n                        return CmdReturnCodes.COMMAND_ERROR.value\n\n            return self.filter_ssp(\n                trestle_root,\n                args.name,\n                args.profile,\n                args.output,\n                args.regenerate,\n                args.version,\n                comp_names,\n                impl_status_values,\n                co_values\n            )\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error generating the filtered ssp')\n\n    def filter_ssp(\n        self,\n        trestle_root: pathlib.Path,\n        ssp_name: str,\n        profile_name: str,\n        out_name: str,\n        regenerate: bool,\n        version: Optional[str],\n        components: Optional[List[str]] = None,\n        implementation_status: Optional[List[str]] = None,\n        control_origination: Optional[List[str]] = None\n    ) -> int:\n\"\"\"\n        Filter the ssp and output new ssp.\n\n        The filtered ssp is based on controls included by the following:\n        profile, components, implementation status, and/or control origination.\n\n        Args:\n            trestle_root: root directory of the trestle workspace\n            ssp_name: name of the ssp model\n            profile_name: name of the optional profile model used for filtering\n            out_name: name of the output ssp model with filtered controls\n            regenerate: whether to regenerate the uuid's in the ssp\n            version: new version for the model\n            components: optional list of component names used for filtering\n            implementation_status: optional list of implementation statuses for filtering\n            control_origination: optional list of control origination values for filtering\n\n        Returns:\n            0 on success, 1 otherwise\n        \"\"\"\n        # load the ssp\n        ssp: ossp.SystemSecurityPlan\n        ssp, _ = load_validate_model_name(trestle_root, ssp_name, ossp.SystemSecurityPlan, FileContentType.JSON)\n        profile_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, profile_name, prof.Profile, FileContentType.JSON\n        )\n\n        if components:\n            raw_comp_names = [ControlReader.simplify_name(name) for name in components]\n            comp_uuids: List[str] = []\n            for component in ssp.system_implementation.components:\n                if ControlReader.simplify_name(component.title) in raw_comp_names:\n                    comp_uuids.append(component.uuid)\n\n            if len(comp_uuids) != len(components):\n                raise TrestleError(\n                    f'Unable to filter the ssp because one of the components {components} is not in the ssp.'\n                )\n\n            # imp_reqs can be by comp\n            # and imp_reqs can have statements that are by comp\n            if comp_uuids:\n                new_imp_reqs: List[ossp.ImplementedRequirement] = []\n                # these are all required to be present\n                for imp_req in ssp.control_implementation.implemented_requirements:\n                    new_by_comps: List[ossp.ByComponent] = []\n                    # by_comps is optional\n                    for by_comp in as_list(imp_req.by_components):\n                        if by_comp.component_uuid in comp_uuids:\n                            new_by_comps.append(by_comp)\n                    imp_req.by_components = none_if_empty(new_by_comps)\n                    new_imp_reqs.append(imp_req)\n                    new_statements: List[ossp.Statement] = []\n                    for statement in as_list(imp_req.statements):\n                        new_by_comps: List[ossp.ByComponent] = []\n                        for by_comp in as_list(statement.by_components):\n                            if by_comp.component_uuid in comp_uuids:\n                                new_by_comps.append(by_comp)\n                        statement.by_components = none_if_empty(new_by_comps)\n                        new_statements.append(statement)\n                    imp_req.statements = none_if_empty(new_statements)\n                ssp.control_implementation.implemented_requirements = new_imp_reqs\n                # now remove any unused components from the ssp\n                new_comp_list: List[ossp.SystemComponent] = []\n                for comp_ in ssp.system_implementation.components:\n                    if comp_.uuid in comp_uuids:\n                        new_comp_list.append(comp_)\n                ssp.system_implementation.components = new_comp_list\n\n        # filter by controls in profile\n        if profile_name:\n            prof_resolver = ProfileResolver()\n            catalog = prof_resolver.get_resolved_profile_catalog(trestle_root, profile_path, show_value_warnings=True)\n            catalog_api = CatalogAPI(catalog=catalog)\n\n            # The input ssp should reference a superset of the controls referenced by the profile\n            # Need to cull references in the ssp to controls not in the profile\n            # Also make sure the output ssp contains imp reqs for all controls in the profile\n            control_imp = ssp.control_implementation\n            ssp_control_ids: Set[str] = set()\n\n            new_set_params: List[ossp.SetParameter] = []\n            for set_param in as_list(control_imp.set_parameters):\n                control = catalog_api._catalog_interface.get_control_by_param_id(set_param.param_id)\n                if control is not None:\n                    new_set_params.append(set_param)\n                    ssp_control_ids.add(control.id)\n            control_imp.set_parameters = none_if_empty(new_set_params)\n\n            new_imp_requirements: List[ossp.ImplementedRequirement] = []\n            for imp_requirement in as_list(control_imp.implemented_requirements):\n                control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n                if control is not None:\n                    new_imp_requirements.append(imp_requirement)\n                    ssp_control_ids.add(control.id)\n            control_imp.implemented_requirements = new_imp_requirements\n\n            # make sure all controls in the profile have implemented reqs in the final ssp\n            if not ssp_control_ids.issuperset(catalog_api._catalog_interface.get_control_ids()):\n                raise TrestleError('Unable to filter the ssp because the profile references controls not in it.')\n\n            ssp.control_implementation = control_imp\n\n        # filter implemented requirements and statements by component implementation status\n        # this will remove any implemented requirements without statements or by_component fields set\n        if implementation_status:\n            new_imp_reqs: List[ossp.ImplementedRequirement] = []\n            # these are all required to be present\n            for imp_req in ssp.control_implementation.implemented_requirements:\n                new_by_comps: List[ossp.ByComponent] = []\n                # by_comps is optional\n                for by_comp in as_list(imp_req.by_components):\n                    if by_comp.implementation_status.state in implementation_status:\n                        new_by_comps.append(by_comp)\n                imp_req.by_components = none_if_empty(new_by_comps)\n\n                new_statements: List[ossp.Statement] = []\n                for statement in as_list(imp_req.statements):\n                    new_by_comps: List[ossp.ByComponent] = []\n                    for by_comp in as_list(statement.by_components):\n                        if by_comp.implementation_status.state in implementation_status:\n                            new_by_comps.append(by_comp)\n                    statement.by_components = none_if_empty(new_by_comps)\n                    if statement.by_components is not None:\n                        new_statements.append(statement)\n                imp_req.statements = none_if_empty(new_statements)\n\n                if imp_req.by_components is not None or imp_req.statements is not None:\n                    new_imp_reqs.append(imp_req)\n\n            ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n        # filter implemented requirements by control origination property.\n        # this will remove any implemented requirements without the control origination\n        # property set\n        if control_origination:\n            new_imp_reqs: List[ossp.ImplementedRequirement] = []\n\n            for imp_requirement in ssp.control_implementation.implemented_requirements:\n                if imp_requirement.props:\n                    for prop in imp_requirement.props:\n                        if prop.name == const.CONTROL_ORIGINATION and prop.value in control_origination:\n                            new_imp_reqs.append(imp_requirement)\n                            # only add the imp requirement one time\n                            break\n\n            ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n        if version:\n            ssp.metadata.version = version\n\n        existing_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n            trestle_root, out_name, ossp.SystemSecurityPlan\n        )\n        if existing_ssp_path is not None:\n            existing_ssp, _ = load_validate_model_name(trestle_root, out_name, ossp.SystemSecurityPlan)\n            if ModelUtils.models_are_equivalent(existing_ssp, ssp):  # type: ignore\n                logger.info('No changes to filtered ssp so ssp not written out.')\n                return CmdReturnCodes.SUCCESS.value\n\n        if regenerate:\n            ssp, _, _ = ModelUtils.regenerate_uuids(ssp)\n\n        ModelUtils.update_last_modified(ssp)\n\n        ModelUtils.save_top_level_model(ssp, trestle_root, out_name, FileContentType.JSON)\n\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPFilter.filter_ssp","title":"filter_ssp(self, trestle_root, ssp_name, profile_name, out_name, regenerate, version, components=None, implementation_status=None, control_origination=None)","text":"

                                                                            Filter the ssp and output new ssp.

                                                                            The filtered ssp is based on controls included by the following: profile, components, implementation status, and/or control origination.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            root directory of the trestle workspace

                                                                            required ssp_name str

                                                                            name of the ssp model

                                                                            required profile_name str

                                                                            name of the optional profile model used for filtering

                                                                            required out_name str

                                                                            name of the output ssp model with filtered controls

                                                                            required regenerate bool

                                                                            whether to regenerate the uuid's in the ssp

                                                                            required version Optional[str]

                                                                            new version for the model

                                                                            required components Optional[List[str]]

                                                                            optional list of component names used for filtering

                                                                            None implementation_status Optional[List[str]]

                                                                            optional list of implementation statuses for filtering

                                                                            None control_origination Optional[List[str]]

                                                                            optional list of control origination values for filtering

                                                                            None

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success, 1 otherwise

                                                                            Source code in trestle/core/commands/author/ssp.py
                                                                            def filter_ssp(\n    self,\n    trestle_root: pathlib.Path,\n    ssp_name: str,\n    profile_name: str,\n    out_name: str,\n    regenerate: bool,\n    version: Optional[str],\n    components: Optional[List[str]] = None,\n    implementation_status: Optional[List[str]] = None,\n    control_origination: Optional[List[str]] = None\n) -> int:\n\"\"\"\n    Filter the ssp and output new ssp.\n\n    The filtered ssp is based on controls included by the following:\n    profile, components, implementation status, and/or control origination.\n\n    Args:\n        trestle_root: root directory of the trestle workspace\n        ssp_name: name of the ssp model\n        profile_name: name of the optional profile model used for filtering\n        out_name: name of the output ssp model with filtered controls\n        regenerate: whether to regenerate the uuid's in the ssp\n        version: new version for the model\n        components: optional list of component names used for filtering\n        implementation_status: optional list of implementation statuses for filtering\n        control_origination: optional list of control origination values for filtering\n\n    Returns:\n        0 on success, 1 otherwise\n    \"\"\"\n    # load the ssp\n    ssp: ossp.SystemSecurityPlan\n    ssp, _ = load_validate_model_name(trestle_root, ssp_name, ossp.SystemSecurityPlan, FileContentType.JSON)\n    profile_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, profile_name, prof.Profile, FileContentType.JSON\n    )\n\n    if components:\n        raw_comp_names = [ControlReader.simplify_name(name) for name in components]\n        comp_uuids: List[str] = []\n        for component in ssp.system_implementation.components:\n            if ControlReader.simplify_name(component.title) in raw_comp_names:\n                comp_uuids.append(component.uuid)\n\n        if len(comp_uuids) != len(components):\n            raise TrestleError(\n                f'Unable to filter the ssp because one of the components {components} is not in the ssp.'\n            )\n\n        # imp_reqs can be by comp\n        # and imp_reqs can have statements that are by comp\n        if comp_uuids:\n            new_imp_reqs: List[ossp.ImplementedRequirement] = []\n            # these are all required to be present\n            for imp_req in ssp.control_implementation.implemented_requirements:\n                new_by_comps: List[ossp.ByComponent] = []\n                # by_comps is optional\n                for by_comp in as_list(imp_req.by_components):\n                    if by_comp.component_uuid in comp_uuids:\n                        new_by_comps.append(by_comp)\n                imp_req.by_components = none_if_empty(new_by_comps)\n                new_imp_reqs.append(imp_req)\n                new_statements: List[ossp.Statement] = []\n                for statement in as_list(imp_req.statements):\n                    new_by_comps: List[ossp.ByComponent] = []\n                    for by_comp in as_list(statement.by_components):\n                        if by_comp.component_uuid in comp_uuids:\n                            new_by_comps.append(by_comp)\n                    statement.by_components = none_if_empty(new_by_comps)\n                    new_statements.append(statement)\n                imp_req.statements = none_if_empty(new_statements)\n            ssp.control_implementation.implemented_requirements = new_imp_reqs\n            # now remove any unused components from the ssp\n            new_comp_list: List[ossp.SystemComponent] = []\n            for comp_ in ssp.system_implementation.components:\n                if comp_.uuid in comp_uuids:\n                    new_comp_list.append(comp_)\n            ssp.system_implementation.components = new_comp_list\n\n    # filter by controls in profile\n    if profile_name:\n        prof_resolver = ProfileResolver()\n        catalog = prof_resolver.get_resolved_profile_catalog(trestle_root, profile_path, show_value_warnings=True)\n        catalog_api = CatalogAPI(catalog=catalog)\n\n        # The input ssp should reference a superset of the controls referenced by the profile\n        # Need to cull references in the ssp to controls not in the profile\n        # Also make sure the output ssp contains imp reqs for all controls in the profile\n        control_imp = ssp.control_implementation\n        ssp_control_ids: Set[str] = set()\n\n        new_set_params: List[ossp.SetParameter] = []\n        for set_param in as_list(control_imp.set_parameters):\n            control = catalog_api._catalog_interface.get_control_by_param_id(set_param.param_id)\n            if control is not None:\n                new_set_params.append(set_param)\n                ssp_control_ids.add(control.id)\n        control_imp.set_parameters = none_if_empty(new_set_params)\n\n        new_imp_requirements: List[ossp.ImplementedRequirement] = []\n        for imp_requirement in as_list(control_imp.implemented_requirements):\n            control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n            if control is not None:\n                new_imp_requirements.append(imp_requirement)\n                ssp_control_ids.add(control.id)\n        control_imp.implemented_requirements = new_imp_requirements\n\n        # make sure all controls in the profile have implemented reqs in the final ssp\n        if not ssp_control_ids.issuperset(catalog_api._catalog_interface.get_control_ids()):\n            raise TrestleError('Unable to filter the ssp because the profile references controls not in it.')\n\n        ssp.control_implementation = control_imp\n\n    # filter implemented requirements and statements by component implementation status\n    # this will remove any implemented requirements without statements or by_component fields set\n    if implementation_status:\n        new_imp_reqs: List[ossp.ImplementedRequirement] = []\n        # these are all required to be present\n        for imp_req in ssp.control_implementation.implemented_requirements:\n            new_by_comps: List[ossp.ByComponent] = []\n            # by_comps is optional\n            for by_comp in as_list(imp_req.by_components):\n                if by_comp.implementation_status.state in implementation_status:\n                    new_by_comps.append(by_comp)\n            imp_req.by_components = none_if_empty(new_by_comps)\n\n            new_statements: List[ossp.Statement] = []\n            for statement in as_list(imp_req.statements):\n                new_by_comps: List[ossp.ByComponent] = []\n                for by_comp in as_list(statement.by_components):\n                    if by_comp.implementation_status.state in implementation_status:\n                        new_by_comps.append(by_comp)\n                statement.by_components = none_if_empty(new_by_comps)\n                if statement.by_components is not None:\n                    new_statements.append(statement)\n            imp_req.statements = none_if_empty(new_statements)\n\n            if imp_req.by_components is not None or imp_req.statements is not None:\n                new_imp_reqs.append(imp_req)\n\n        ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n    # filter implemented requirements by control origination property.\n    # this will remove any implemented requirements without the control origination\n    # property set\n    if control_origination:\n        new_imp_reqs: List[ossp.ImplementedRequirement] = []\n\n        for imp_requirement in ssp.control_implementation.implemented_requirements:\n            if imp_requirement.props:\n                for prop in imp_requirement.props:\n                    if prop.name == const.CONTROL_ORIGINATION and prop.value in control_origination:\n                        new_imp_reqs.append(imp_requirement)\n                        # only add the imp requirement one time\n                        break\n\n        ssp.control_implementation.implemented_requirements = new_imp_reqs\n\n    if version:\n        ssp.metadata.version = version\n\n    existing_ssp_path = ModelUtils.get_model_path_for_name_and_class(\n        trestle_root, out_name, ossp.SystemSecurityPlan\n    )\n    if existing_ssp_path is not None:\n        existing_ssp, _ = load_validate_model_name(trestle_root, out_name, ossp.SystemSecurityPlan)\n        if ModelUtils.models_are_equivalent(existing_ssp, ssp):  # type: ignore\n            logger.info('No changes to filtered ssp so ssp not written out.')\n            return CmdReturnCodes.SUCCESS.value\n\n    if regenerate:\n        ssp, _, _ = ModelUtils.regenerate_uuids(ssp)\n\n    ModelUtils.update_last_modified(ssp)\n\n    ModelUtils.save_top_level_model(ssp, trestle_root, out_name, FileContentType.JSON)\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPGenerate","title":" SSPGenerate (AuthorCommonCommand) ","text":"

                                                                            Generate SSP in markdown form from a Profile.

                                                                            Source code in trestle/core/commands/author/ssp.py
                                                                            class SSPGenerate(AuthorCommonCommand):\n\"\"\"Generate SSP in markdown form from a Profile.\"\"\"\n\n    name = 'ssp-generate'\n\n    def _init_arguments(self) -> None:\n        file_help_str = 'Main profile href, or name of the profile model in the trestle workspace'\n        self.add_argument('-p', '--profile', help=file_help_str, required=True, type=str)\n        self.add_argument(\n            '-o', '--output', help='Name of the output generated ssp markdown folder', required=True, type=str\n        )  # noqa E501\n        self.add_argument('-cd', '--compdefs', help=const.HELP_COMPDEFS, required=False, type=str)\n\n        ls_help_str = 'Leveraged ssp with inheritable controls href or name in the trestle_workspace'\n        self.add_argument('-ls', '--leveraged-ssp', help=ls_help_str, required=False, type=str)\n\n        self.add_argument('-y', '--yaml-header', help=const.HELP_YAML_PATH, required=False, type=str)\n        self.add_argument(\n            '-fo', '--force-overwrite', help=const.HELP_FO_OUTPUT, required=False, action='store_true', default=False\n        )\n        self.add_argument(\n            '-ohv',\n            '--overwrite-header-values',\n            help=const.HELP_OVERWRITE_HEADER_VALUES,\n            required=False,\n            action='store_true',\n            default=False\n        )\n        self.add_argument(\n            '-iap',\n            '--include-all-parts',\n            help=const.HELP_INCLUDE_ALL_PARTS,\n            required=False,\n            action='store_true',\n            default=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = args.trestle_root\n            if not file_utils.is_directory_name_allowed(args.output):\n                raise TrestleError(f'{args.output} is not an allowed directory name')\n\n            yaml_header: Dict[str, Any] = {}\n            if args.yaml_header:\n                try:\n                    logging.debug(f'Loading yaml header file {args.yaml_header}')\n                    yaml = YAML()\n                    yaml_header = yaml.load(pathlib.Path(args.yaml_header).open('r'))\n                except YAMLError as e:\n                    raise TrestleError(f'YAML error loading yaml header {args.yaml_header} for ssp generation: {e}')\n\n            compdef_name_list = comma_sep_to_list(args.compdefs)\n\n            md_path = trestle_root / args.output\n\n            return self._generate_ssp_markdown(\n                trestle_root,\n                args.profile,\n                compdef_name_list,\n                args.leveraged_ssp,\n                md_path,\n                yaml_header,\n                args.overwrite_header_values,\n                args.force_overwrite,\n                args.include_all_parts\n            )\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while writing markdown from catalog')\n\n    def _generate_ssp_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        profile_name_or_href: str,\n        compdef_name_list: List[str],\n        leveraged_ssp_name_or_href: str,\n        md_path: pathlib.Path,\n        yaml_header: Dict[str, Any],\n        overwrite_header_values: bool,\n        force_overwrite: bool,\n        include_all_parts: bool\n    ) -> int:\n\"\"\"\n        Generate the ssp markdown from the profile and compdefs.\n\n        Notes:\n        Get RPC from profile.\n        For each compdef:\n            For each comp:\n                Load top level rules\n                for each control_imp:\n                    Load rules params values\n                    For each imp_req (bound to 1 control):\n                        Load control level rules and status\n                        Load part level rules\n                        If rules apply then write out control and add to list written out\n                        If control exists, read it and insert content\n        \"\"\"\n        if force_overwrite:\n            try:\n                logger.info(f'Overwriting the content in {md_path}.')\n                clear_folder(pathlib.Path(md_path))\n            except TrestleError as e:  # pragma: no cover\n                raise TrestleError(f'Unable to overwrite contents of {md_path}: {e}')\n\n        context = ControlContext.generate(ContextPurpose.SSP, True, trestle_root, md_path)\n        context.cli_yaml_header = yaml_header\n        context.sections_dict = None\n        context.prompt_responses = True\n        context.overwrite_header_values = overwrite_header_values\n        context.allowed_sections = None\n        context.comp_def_name_list = compdef_name_list\n        context.include_all_parts = include_all_parts\n\n        # if file not recognized as URI form, assume it represents name of file in trestle directory\n        profile_in_trestle_dir = '://' not in profile_name_or_href\n        profile_href = profile_name_or_href\n        if profile_in_trestle_dir:\n            local_path = f'profiles/{profile_name_or_href}/profile.json'\n            profile_href = const.TRESTLE_HREF_HEADING + local_path\n            profile_path = trestle_root / local_path\n            _, _, context.profile = ModelUtils.load_distributed(profile_path, trestle_root)\n        else:\n            fetcher = FetcherFactory.get_fetcher(trestle_root, profile_href)\n            context.profile = fetcher.get_oscal()\n            profile_path = profile_href\n\n        profile_resolver = ProfileResolver()\n        # in ssp context we want to see missing value warnings\n        resolved_catalog = profile_resolver.get_resolved_profile_catalog(\n            trestle_root,\n            profile_path,\n            block_params=False,\n            params_format='[.]',\n            param_rep=ParameterRep.ASSIGNMENT_FORM,\n            show_value_warnings=True\n        )\n\n        catalog_api = CatalogAPI(catalog=resolved_catalog, context=context)\n\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG] = {}\n        profile_header = {'title': context.profile.metadata.title, 'href': profile_href}\n\n        context.cli_yaml_header[const.TRESTLE_GLOBAL_TAG][const.PROFILE] = profile_header\n\n        catalog_api.write_catalog_as_markdown()\n\n        # Generate inheritance view after controls view completes\n        if leveraged_ssp_name_or_href:\n            self._generate_inheritance_markdown(trestle_root, leveraged_ssp_name_or_href, resolved_catalog, md_path)\n\n        return CmdReturnCodes.SUCCESS.value\n\n    def _generate_inheritance_markdown(\n        self,\n        trestle_root: pathlib.Path,\n        leveraged_ssp_name_or_href: str,\n        resolved_catalog: CatalogInterface,\n        md_path: str\n    ) -> None:\n\"\"\"\n        Generate markdown for inheritance view.\n\n        Notes:\n            This will create the inheritance view markdown files in the same directory as the ssp markdown files.\n            The information will be from the leveraged ssp, but filtered by the chosen profile to ensure only relevant\n            controls are present for mapping.\n        \"\"\"\n        # if file not recognized as URI form, assume it represents name of file in trestle directory\n        ssp_in_trestle_dir = '://' not in leveraged_ssp_name_or_href\n        ssp_href = leveraged_ssp_name_or_href\n        if ssp_in_trestle_dir:\n            local_path = f'{const.MODEL_DIR_SSP}/{leveraged_ssp_name_or_href}/system-security-plan.json'\n            ssp_href = const.TRESTLE_HREF_HEADING + local_path\n\n        inheritance_view_path: pathlib.Path = md_path.joinpath(const.INHERITANCE_VIEW_DIR)\n        inheritance_view_path.mkdir(exist_ok=True)\n        logger.debug(f'Creating content for inheritance view in {inheritance_view_path}')\n\n        ssp_inheritance_api = SSPInheritanceAPI(inheritance_view_path, trestle_root)\n\n        # Filter the ssp implemented requirements by the catalog specified\n        catalog_api: CatalogAPI = CatalogAPI(catalog=resolved_catalog)\n        ssp_inheritance_api.write_inheritance_as_markdown(ssp_href, catalog_api)\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.ssp/#trestle.core.commands.author.ssp.SSPGenerate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/","title":"template_versioning","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning","title":"trestle.core.commands.author.versioning.template_versioning","text":"

                                                                            A Template Versioning.

                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning","title":" TemplateVersioning ","text":"

                                                                            Template versioning solution.

                                                                            1. Load template with a specified version.
                                                                              1. Template version can be specified via -tv flag
                                                                              2. If no version specified the latest version will be used by default.
                                                                              3. Otherwise use the templates from the specified version.
                                                                            2. Backward compatibility.
                                                                              1. Version 0.0.1 will be reserved for the template versions prior to this change.
                                                                              2. If the old template path is detected (i.e. without the template version). then the filesystem will be updated to the new path with the version.
                                                                              3. Upon first run, old template versions prior to this change will be placed to the folder 0.0.1.
                                                                              4. If templates have no headers then 0.0.1 version will be used.
                                                                            3. Versioning organization.
                                                                              1. Template and instance version is added both: in the file system (via path) and in the headers or metadata.
                                                                            4. Instance version validation.
                                                                              1. Markdown:
                                                                                1. When validating the instance the header will be used to validate the version.
                                                                              2. Drawio:
                                                                                1. When validating the instance the metadata will be used to validate the version.
                                                                            Source code in trestle/core/commands/author/versioning/template_versioning.py
                                                                            class TemplateVersioning:\n\"\"\"\n    Template versioning solution.\n\n    1. Load template with a specified version.\n        1. Template version can be specified via -tv flag\n        2. If no version specified the latest version will be used by default.\n        3. Otherwise use the templates from the specified version.\n    2. Backward compatibility.\n        1. Version 0.0.1 will be reserved for the template versions prior to this change.\n        2. If the old template path is detected (i.e. without the template version).\n            then the filesystem will be updated to the new path with the version.\n        3. Upon first run, old template versions prior to this change will be placed to the folder 0.0.1.\n        4. If templates have no headers then 0.0.1 version will be used.\n    3. Versioning organization.\n        1. Template and instance version is added both: in the file system (via path) and in the headers or metadata.\n    4. Instance version validation.\n        1. Markdown:\n            1. When validating the instance the header will be used to validate the version.\n        2. Drawio:\n            1. When validating the instance the metadata will be used to validate the version.\n    \"\"\"\n\n    @staticmethod\n    def update_template_folder_structure(task_path: Path) -> None:\n\"\"\"\n        Automatically detect whether the path is an old style and update it.\n\n        An old-style path is a path of the form:\n         root_folder/.trestle/author/{template_name}/{template_objects}\n        The new version path is a path of the form:\n         root_folder/.trestle/author/{template_name}/{version}/{template_objects}\n        By default all old-style templates will be updated to version 0.0.1\n        \"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n\n        try:\n            all_files_wo_version = list(\n                filter(lambda p: p.is_file(), file_utils.iterdir_without_hidden_files(task_path))\n            )\n\n            pattern = re.compile(TEMPLATE_VERSION_REGEX)\n            all_non_template_directories = list(\n                filter(\n                    lambda p: p.is_dir() and pattern.search(p.parts[-1]) is None,\n                    file_utils.iterdir_without_hidden_files(task_path)\n                )\n            )\n\n            new_dir = Path(f'{task_path}/{START_TEMPLATE_VERSION}')\n            new_dir.mkdir(parents=True, exist_ok=True)\n\n            if len(all_files_wo_version) == 0:\n                logger.debug('No templates outside of the version folders.')\n                # if the base template folder is empty, delete it\n                if len(list(new_dir.iterdir())) == 0:\n                    new_dir.rmdir()\n\n            for f in all_files_wo_version + all_non_template_directories:\n                if f.is_file():\n                    shutil.copy(f, new_dir)\n                elif f.is_dir():\n                    shutil.copytree(f, new_dir / f.name)\n\n            for p in all_files_wo_version + all_non_template_directories:\n                if p.is_dir():\n                    shutil.rmtree(p)\n                else:\n                    p.unlink()\n\n        except OSError as e:\n            raise TrestleError(f'Error while updating template folder: {e}')\n        except Exception as e:\n            raise TrestleError(f'Unexpected error while updating template folder: {e}')\n\n    @staticmethod\n    def get_versioned_template_dir(task_path: Path, version: Optional[str] = None) -> Path:\n\"\"\"\n        Get a template folder of the specified version.\n\n        If no version is given, the latest version of template will be returned\n        \"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n        latest_path = None\n        if version is None:\n            latest_path, _ = TemplateVersioning.get_latest_version_for_task(task_path)\n        else:\n            latest_path = Path(f'{task_path}/{version}/')\n\n        if not latest_path.exists():\n            raise TrestleError(f'The task: {task_path} with version: {version} does not exists.')\n\n        return latest_path\n\n    @staticmethod\n    def get_latest_version_for_task(task_path: Path) -> Tuple[Path, str]:\n\"\"\"Get latest version of the template for the given task.\"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n\n        all_versions = TemplateVersioning.get_all_versions_for_task(task_path)\n        max_version = START_TEMPLATE_VERSION\n\n        if len(all_versions) == 0:\n            logger.debug(f'No template versions were found for task: {task_path}, defaulting to 0.0.1')\n            max_version = START_TEMPLATE_VERSION\n        else:\n            max_version = max(all_versions)\n\n        latest_path = Path(f'{task_path}/{max_version}')\n\n        return latest_path, max_version\n\n    @staticmethod\n    def get_all_versions_for_task(task_path: Path) -> List[str]:\n\"\"\"Get all versions for the task.\"\"\"\n        pattern = re.compile(TEMPLATE_VERSION_REGEX)\n        all_versions = []\n        max_version = START_TEMPLATE_VERSION\n        for p in task_path.iterdir():\n            if p.is_dir() and pattern.search(p.parts[-1]) is not None:\n                match = pattern.search(p.parts[-1]).string\n                all_versions.append(match)\n                if match > max_version:\n                    max_version = match\n\n        return all_versions\n\n    @staticmethod\n    def write_versioned_template(\n        resource_name: str, task_path: Path, target_file: Path, version: Optional[str] = None\n    ) -> None:\n\"\"\"\n        Write a template with the header or metadata of a specified version.\n\n        If no version was given the latest version for the task will be used.\n\n        Args:\n            resource_name:  Template resource name\n            task_path: Task path\n            target_file: File path where template will be written\n            version: return a resource of a specific version\n\n        Returns:\n            A dotted path of a versioned template, list of all available versions\n        \"\"\"\n        TemplateVersioning._check_if_exists_and_dir(task_path)\n        try:\n            templates_resource_path = TRESTLE_RESOURCES + '.templates'\n\n            ref = importlib_resources.files(templates_resource_path) / resource_name\n            with importlib_resources.as_file(ref) as generic_template:\n                if version is None:\n                    _, version = TemplateVersioning.get_latest_version_for_task(task_path)\n\n                # modify header/metadata in the template\n                if generic_template.suffix == MARKDOWN_FILE_EXT:\n                    md_api = MarkdownAPI()\n                    header, md_body = md_api.processor.read_markdown_wo_processing(generic_template)\n                    header[TEMPLATE_VERSION_HEADER] = version\n                    md_api.write_markdown_with_header(target_file, header, md_body)\n                    logger.debug(f'Successfully written template markdown to {target_file}')\n                elif generic_template.suffix == DRAWIO_FILE_EXT:\n                    drawio = DrawIO(generic_template)\n                    metadata = drawio.get_metadata()[0]\n                    metadata[TEMPLATE_VERSION_HEADER] = version\n\n                    drawio.write_drawio_with_metadata(generic_template, metadata, 0, target_file)\n                    logger.debug(f'Successfully written template drawio to {target_file}')\n                else:\n                    raise TrestleError(f'Unsupported template file extension {generic_template.suffix}')\n        except OSError as e:\n            raise TrestleError(f'Error while updating template folder: {e}')\n\n    @staticmethod\n    def is_valid_version(template_version: str) -> bool:\n\"\"\"Check if the version format is correct.\"\"\"\n        if template_version is None:\n            return True  # we can have empty version\n        if template_version == '0.0.0':\n            return False\n        version_regex = r'^[0-9]+\\.[0-9]+\\.[0-9]+$'\n        pattern = re.compile(version_regex)\n        if pattern.search(template_version):\n            return True\n        else:\n            return False\n\n    @staticmethod\n    def _check_if_exists_and_dir(task_path: Path) -> None:\n        if not task_path.exists():\n            raise TrestleError(f'Path: {task_path} does not exists.')\n\n        if not task_path.is_dir():\n            raise TrestleError(f'File {task_path} passed, however template directory is expected.')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.get_all_versions_for_task","title":"get_all_versions_for_task(task_path) staticmethod","text":"

                                                                            Get all versions for the task.

                                                                            Source code in trestle/core/commands/author/versioning/template_versioning.py
                                                                            @staticmethod\ndef get_all_versions_for_task(task_path: Path) -> List[str]:\n\"\"\"Get all versions for the task.\"\"\"\n    pattern = re.compile(TEMPLATE_VERSION_REGEX)\n    all_versions = []\n    max_version = START_TEMPLATE_VERSION\n    for p in task_path.iterdir():\n        if p.is_dir() and pattern.search(p.parts[-1]) is not None:\n            match = pattern.search(p.parts[-1]).string\n            all_versions.append(match)\n            if match > max_version:\n                max_version = match\n\n    return all_versions\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.get_latest_version_for_task","title":"get_latest_version_for_task(task_path) staticmethod","text":"

                                                                            Get latest version of the template for the given task.

                                                                            Source code in trestle/core/commands/author/versioning/template_versioning.py
                                                                            @staticmethod\ndef get_latest_version_for_task(task_path: Path) -> Tuple[Path, str]:\n\"\"\"Get latest version of the template for the given task.\"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n\n    all_versions = TemplateVersioning.get_all_versions_for_task(task_path)\n    max_version = START_TEMPLATE_VERSION\n\n    if len(all_versions) == 0:\n        logger.debug(f'No template versions were found for task: {task_path}, defaulting to 0.0.1')\n        max_version = START_TEMPLATE_VERSION\n    else:\n        max_version = max(all_versions)\n\n    latest_path = Path(f'{task_path}/{max_version}')\n\n    return latest_path, max_version\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.get_versioned_template_dir","title":"get_versioned_template_dir(task_path, version=None) staticmethod","text":"

                                                                            Get a template folder of the specified version.

                                                                            If no version is given, the latest version of template will be returned

                                                                            Source code in trestle/core/commands/author/versioning/template_versioning.py
                                                                            @staticmethod\ndef get_versioned_template_dir(task_path: Path, version: Optional[str] = None) -> Path:\n\"\"\"\n    Get a template folder of the specified version.\n\n    If no version is given, the latest version of template will be returned\n    \"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n    latest_path = None\n    if version is None:\n        latest_path, _ = TemplateVersioning.get_latest_version_for_task(task_path)\n    else:\n        latest_path = Path(f'{task_path}/{version}/')\n\n    if not latest_path.exists():\n        raise TrestleError(f'The task: {task_path} with version: {version} does not exists.')\n\n    return latest_path\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.is_valid_version","title":"is_valid_version(template_version) staticmethod","text":"

                                                                            Check if the version format is correct.

                                                                            Source code in trestle/core/commands/author/versioning/template_versioning.py
                                                                            @staticmethod\ndef is_valid_version(template_version: str) -> bool:\n\"\"\"Check if the version format is correct.\"\"\"\n    if template_version is None:\n        return True  # we can have empty version\n    if template_version == '0.0.0':\n        return False\n    version_regex = r'^[0-9]+\\.[0-9]+\\.[0-9]+$'\n    pattern = re.compile(version_regex)\n    if pattern.search(template_version):\n        return True\n    else:\n        return False\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.update_template_folder_structure","title":"update_template_folder_structure(task_path) staticmethod","text":"

                                                                            Automatically detect whether the path is an old style and update it.

                                                                            An old-style path is a path of the form: root_folder/.trestle/author/{template_name}/{template_objects} The new version path is a path of the form: root_folder/.trestle/author/{template_name}/{version}/{template_objects} By default all old-style templates will be updated to version 0.0.1

                                                                            Source code in trestle/core/commands/author/versioning/template_versioning.py
                                                                            @staticmethod\ndef update_template_folder_structure(task_path: Path) -> None:\n\"\"\"\n    Automatically detect whether the path is an old style and update it.\n\n    An old-style path is a path of the form:\n     root_folder/.trestle/author/{template_name}/{template_objects}\n    The new version path is a path of the form:\n     root_folder/.trestle/author/{template_name}/{version}/{template_objects}\n    By default all old-style templates will be updated to version 0.0.1\n    \"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n\n    try:\n        all_files_wo_version = list(\n            filter(lambda p: p.is_file(), file_utils.iterdir_without_hidden_files(task_path))\n        )\n\n        pattern = re.compile(TEMPLATE_VERSION_REGEX)\n        all_non_template_directories = list(\n            filter(\n                lambda p: p.is_dir() and pattern.search(p.parts[-1]) is None,\n                file_utils.iterdir_without_hidden_files(task_path)\n            )\n        )\n\n        new_dir = Path(f'{task_path}/{START_TEMPLATE_VERSION}')\n        new_dir.mkdir(parents=True, exist_ok=True)\n\n        if len(all_files_wo_version) == 0:\n            logger.debug('No templates outside of the version folders.')\n            # if the base template folder is empty, delete it\n            if len(list(new_dir.iterdir())) == 0:\n                new_dir.rmdir()\n\n        for f in all_files_wo_version + all_non_template_directories:\n            if f.is_file():\n                shutil.copy(f, new_dir)\n            elif f.is_dir():\n                shutil.copytree(f, new_dir / f.name)\n\n        for p in all_files_wo_version + all_non_template_directories:\n            if p.is_dir():\n                shutil.rmtree(p)\n            else:\n                p.unlink()\n\n    except OSError as e:\n        raise TrestleError(f'Error while updating template folder: {e}')\n    except Exception as e:\n        raise TrestleError(f'Unexpected error while updating template folder: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.author.versioning.template_versioning/#trestle.core.commands.author.versioning.template_versioning.TemplateVersioning.write_versioned_template","title":"write_versioned_template(resource_name, task_path, target_file, version=None) staticmethod","text":"

                                                                            Write a template with the header or metadata of a specified version.

                                                                            If no version was given the latest version for the task will be used.

                                                                            Parameters:

                                                                            Name Type Description Default resource_name str

                                                                            Template resource name

                                                                            required task_path Path

                                                                            Task path

                                                                            required target_file Path

                                                                            File path where template will be written

                                                                            required version Optional[str]

                                                                            return a resource of a specific version

                                                                            None

                                                                            Returns:

                                                                            Type Description None

                                                                            A dotted path of a versioned template, list of all available versions

                                                                            Source code in trestle/core/commands/author/versioning/template_versioning.py
                                                                            @staticmethod\ndef write_versioned_template(\n    resource_name: str, task_path: Path, target_file: Path, version: Optional[str] = None\n) -> None:\n\"\"\"\n    Write a template with the header or metadata of a specified version.\n\n    If no version was given the latest version for the task will be used.\n\n    Args:\n        resource_name:  Template resource name\n        task_path: Task path\n        target_file: File path where template will be written\n        version: return a resource of a specific version\n\n    Returns:\n        A dotted path of a versioned template, list of all available versions\n    \"\"\"\n    TemplateVersioning._check_if_exists_and_dir(task_path)\n    try:\n        templates_resource_path = TRESTLE_RESOURCES + '.templates'\n\n        ref = importlib_resources.files(templates_resource_path) / resource_name\n        with importlib_resources.as_file(ref) as generic_template:\n            if version is None:\n                _, version = TemplateVersioning.get_latest_version_for_task(task_path)\n\n            # modify header/metadata in the template\n            if generic_template.suffix == MARKDOWN_FILE_EXT:\n                md_api = MarkdownAPI()\n                header, md_body = md_api.processor.read_markdown_wo_processing(generic_template)\n                header[TEMPLATE_VERSION_HEADER] = version\n                md_api.write_markdown_with_header(target_file, header, md_body)\n                logger.debug(f'Successfully written template markdown to {target_file}')\n            elif generic_template.suffix == DRAWIO_FILE_EXT:\n                drawio = DrawIO(generic_template)\n                metadata = drawio.get_metadata()[0]\n                metadata[TEMPLATE_VERSION_HEADER] = version\n\n                drawio.write_drawio_with_metadata(generic_template, metadata, 0, target_file)\n                logger.debug(f'Successfully written template drawio to {target_file}')\n            else:\n                raise TrestleError(f'Unsupported template file extension {generic_template.suffix}')\n    except OSError as e:\n        raise TrestleError(f'Error while updating template folder: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.command_docs/","title":"command_docs","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs","title":"trestle.core.commands.command_docs","text":"

                                                                            Trestle command abstraction.

                                                                            Improves parsing until such a point as ILCLI is fixed.

                                                                            "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandBase","title":" CommandBase (Command) ","text":"

                                                                            Linear extension to the ILCLI interface to use documentation string more.

                                                                            Trestle commands not requiring trestle-root should extend from this class.

                                                                            Source code in trestle/core/commands/command_docs.py
                                                                            class CommandBase(Command):\n\"\"\"Linear extension to the ILCLI interface to use documentation string more.\n\n    Trestle commands not requiring trestle-root should extend from this class.\n    \"\"\"\n\n    # Example commands extedning from this class - init', 'trestle', 'version', 'partial-object-validate'\n    def __init__(\n        self,\n        parser: Optional[argparse.ArgumentParser] = None,\n        parent: Optional[Command] = None,\n        name: Optional[str] = None,\n        out: Optional[TextIO] = None,\n        err: Optional[TextIO] = None\n    ) -> None:\n\"\"\"Override default ILCLI behaviour to include class documentation in command help description.\"\"\"\n        super(CommandBase, self).__init__(parser, parent, name, out, err)\n        self.parser.description = self.__doc__\n
                                                                            "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandBase.__init__","title":"__init__(self, parser=None, parent=None, name=None, out=None, err=None) special","text":"

                                                                            Override default ILCLI behaviour to include class documentation in command help description.

                                                                            Source code in trestle/core/commands/command_docs.py
                                                                            def __init__(\n    self,\n    parser: Optional[argparse.ArgumentParser] = None,\n    parent: Optional[Command] = None,\n    name: Optional[str] = None,\n    out: Optional[TextIO] = None,\n    err: Optional[TextIO] = None\n) -> None:\n\"\"\"Override default ILCLI behaviour to include class documentation in command help description.\"\"\"\n    super(CommandBase, self).__init__(parser, parent, name, out, err)\n    self.parser.description = self.__doc__\n
                                                                            "},{"location":"api_reference/trestle.core.commands.command_docs/#trestle.core.commands.command_docs.CommandPlusDocs","title":" CommandPlusDocs (CommandBase) ","text":"

                                                                            This class validates trestle-root argument.

                                                                            Trestle commands requiring trestle-root should extend from this class. All commands that extend this class will validate the state of trestle workspace.

                                                                            Source code in trestle/core/commands/command_docs.py
                                                                            class CommandPlusDocs(CommandBase):\n\"\"\"This class validates trestle-root argument.\n\n    Trestle commands requiring trestle-root should extend from this class.\n    All commands that extend this class will validate the state of trestle workspace.\n    \"\"\"\n\n    def _validate_arguments(self, args: argparse.ArgumentParser) -> int:\n\"\"\"Check trestle-root argument is a valid trestle root directory.\"\"\"\n        root = file_utils.extract_trestle_project_root(args.trestle_root)  # type: ignore\n        if root is None:\n            logger.error(f'Given directory {args.trestle_root} is not in a valid trestle root directory')\n            return CmdReturnCodes.TRESTLE_ROOT_ERROR.value\n        is_oscal_dir_valid = file_utils.check_oscal_directories(args.trestle_root)  # type: ignore\n        if not is_oscal_dir_valid:\n            return CmdReturnCodes.TRESTLE_ROOT_ERROR.value\n        args.trestle_root = root  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/","title":"cmd_utils","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils","title":"trestle.core.commands.common.cmd_utils","text":"

                                                                            Trestle command related utilities.

                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.clear_folder","title":"clear_folder(folder_path)","text":"

                                                                            Clear all contents of the specified folder.

                                                                            Source code in trestle/core/commands/common/cmd_utils.py
                                                                            def clear_folder(folder_path: pathlib.Path) -> None:\n\"\"\"Clear all contents of the specified folder.\"\"\"\n    if not folder_path.exists() or not folder_path.is_dir():\n        return\n    try:\n        shutil.rmtree(folder_path)\n    except OSError as e:  # pragma: no cover\n        raise TrestleError(f'Error deleting contents of {folder_path}: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.model_type_is_too_granular","title":"model_type_is_too_granular(model_type)","text":"

                                                                            Is an model_type too fine to split.

                                                                            Source code in trestle/core/commands/common/cmd_utils.py
                                                                            def model_type_is_too_granular(model_type: Type[Any]) -> bool:\n\"\"\"Is an model_type too fine to split.\"\"\"\n    if type_utils.is_collection_field_type(model_type):\n        return False\n    if hasattr(model_type, '__fields__') and '__root__' in model_type.__fields__:\n        return True\n    if model_type.__name__ in ['str', 'ConstrainedStrValue', 'int', 'float', 'datetime']:\n        return True\n    return False\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.parse_chain","title":"parse_chain(model_obj, path_parts, relative_path=None)","text":"

                                                                            Parse the model chain starting from the beginning.

                                                                            Parameters:

                                                                            Name Type Description Default model_obj Optional[trestle.core.base_model.OscalBaseModel]

                                                                            Model to use for inspecting available elements, if available or none

                                                                            required path_parts List[str]

                                                                            list of string paths to parse including wildcards

                                                                            required relative_path Optional[pathlib.Path]

                                                                            Optional relative path (w.r.t trestle workspace root directory)

                                                                            None

                                                                            Returns:

                                                                            Type Description List[trestle.core.models.elements.ElementPath]

                                                                            List of ElementPath

                                                                            Source code in trestle/core/commands/common/cmd_utils.py
                                                                            def parse_chain(\n    model_obj: Union[OscalBaseModel, None],\n    path_parts: List[str],\n    relative_path: Optional[pathlib.Path] = None\n) -> List[ElementPath]:\n\"\"\"Parse the model chain starting from the beginning.\n\n    Args:\n        model_obj: Model to use for inspecting available elements, if available or none\n        path_parts: list of string paths to parse including wildcards\n        relative_path: Optional relative path (w.r.t trestle workspace root directory)\n\n    Returns:\n        List of ElementPath\n    \"\"\"\n    element_paths: List[ElementPath] = []\n    sub_model = model_obj\n    have_model_to_parse = model_obj is not None\n\n    prev_element_path = None\n    latest_path = None\n    parent_model = path_parts[0]\n    i = 1\n    while i < len(path_parts):\n        p = path_parts[i]\n\n        # if hit wildcard create element path up to this point\n        if p == ElementPath.WILDCARD and len(element_paths) > 0:\n            # append wildcard to the latest element path\n            latest_path = element_paths.pop()\n            if latest_path.get_last() == ElementPath.WILDCARD:\n                raise TrestleError(f'Invalid element path with consecutive {ElementPath.WILDCARD}')\n\n            latest_path_str = ElementPath.PATH_SEPARATOR.join([latest_path.to_string(), p])\n            element_path = ElementPath(latest_path_str, latest_path.get_parent())\n        else:\n            # create and append element_path\n            # at this point sub_model may be a list of items\n            # new element path is needed only if any of the items contains the desired part\n            if p != ElementPath.WILDCARD:\n                new_attrib = str_utils.dash_to_underscore(p)\n                if isinstance(sub_model, list):\n                    for item in sub_model:\n                        # go into the list and find one with requested part\n                        sub_item = getattr(item, new_attrib, None)\n                        if sub_item is not None:\n                            sub_model = sub_item\n                            break\n                else:\n                    sub_model = getattr(sub_model, new_attrib, None)\n            if have_model_to_parse and sub_model is None:\n                return element_paths\n            p = ElementPath.PATH_SEPARATOR.join([parent_model, p])\n            element_path = ElementPath(p, parent_path=prev_element_path)\n\n        # If the path has wildcard and there are more parts later,\n        # get the parent model for the alias path\n        # If path has wildcard and it does not refer to a list, then there can be nothing after *\n        if element_path.get_last() == ElementPath.WILDCARD:\n            full_path_str = ElementPath.PATH_SEPARATOR.join(element_path.get_full_path_parts()[:-1])\n            parent_model = ModelUtils.get_singular_alias(full_path_str, relative_path)\n            # Does wildcard mean we need to inspect the sub_model to determine what can be split off from it?\n            # If it has __root__ it may mean it contains a list of objects and should be split as a list\n            if isinstance(sub_model, OscalBaseModel):\n                root = getattr(sub_model, '__root__', None)\n                if root is None or not isinstance(root, list):\n                    # Cannot have parts beyond * if it isn't a list\n                    if i < len(path_parts) - 1:\n                        raise TrestleError(\n                            f'Cannot split beyond * when the wildcard does not refer to a list.  Path: {path_parts}'\n                        )\n                    for key in sub_model.__fields__.keys():\n                        # only create element path is item is present in the sub_model\n                        if getattr(sub_model, key, None) is None:\n                            continue\n                        new_alias = str_utils.underscore_to_dash(key)\n                        new_path = full_path_str + '.' + new_alias\n                        if not split_is_too_fine(new_path, model_obj):\n                            # to add parts of an element, need to add two links\n                            # prev_element_path may be None, for example catalog.*\n                            if prev_element_path is not None:\n                                element_paths.append(prev_element_path)\n                            element_paths.append(ElementPath(parent_model + '.' + new_alias, latest_path))\n                    # Since wildcard is last in the chain when splitting an oscal model we are done\n                    return element_paths\n        else:\n            parent_model = element_path.get_element_name()\n\n        # store values for next cycle\n        prev_element_path = element_path\n        element_paths.append(element_path)\n        i += 1\n    return element_paths\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.parse_element_arg","title":"parse_element_arg(model_obj, element_arg, relative_path=None)","text":"

                                                                            Parse an element arg string into a list of ElementPath.

                                                                            Parameters:

                                                                            Name Type Description Default model_obj Optional[trestle.core.base_model.OscalBaseModel]

                                                                            The OscalBaseModel being inspected to determine available elements that can be split

                                                                            required element_arg str

                                                                            Single element path, as a string.

                                                                            required relative_path Optional[pathlib.Path]

                                                                            Optional relative path (from trestle root) used to validate element args are valid.

                                                                            None

                                                                            Returns:

                                                                            Type Description List[trestle.core.models.elements.ElementPath]

                                                                            The requested parsed list of ElementPath for use in split

                                                                            Source code in trestle/core/commands/common/cmd_utils.py
                                                                            def parse_element_arg(\n    model_obj: Union[OscalBaseModel, None],\n    element_arg: str,\n    relative_path: Optional[pathlib.Path] = None\n) -> List[ElementPath]:\n\"\"\"Parse an element arg string into a list of ElementPath.\n\n    Args:\n        model_obj: The OscalBaseModel being inspected to determine available elements that can be split\n        element_arg: Single element path, as a string.\n        relative_path: Optional relative path (from trestle root) used to validate element args are valid.\n    Returns:\n        The requested parsed list of ElementPath for use in split\n    \"\"\"\n    element_arg = element_arg.strip()\n\n    if element_arg == '*':\n        raise TrestleError('Invalid element path containing only a single wildcard.')\n\n    if element_arg == '':\n        raise TrestleError('Invalid element path is empty string.')\n\n    # search for wildcards and create paths with its parent path\n    path_parts = element_arg.split(ElementPath.PATH_SEPARATOR)\n    if len(path_parts) <= 1:\n        raise TrestleError(f'Invalid element path \"{element_arg}\" with only one element and no wildcard')\n\n    element_paths = parse_chain(model_obj, path_parts, relative_path)\n\n    if len(element_paths) <= 0:\n        # don't complain if nothing to split\n        pass\n\n    return element_paths\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.parse_element_args","title":"parse_element_args(model, element_args, relative_path=None)","text":"

                                                                            Parse element args into a list of ElementPath.

                                                                            The element paths are either simple links of two elements, or two elements followed by *. The * represents either a list of the items in that element, or a splitting of that element into its parts. The only parts split off are the non-trivial ones determined by the granularity check.

                                                                            contextual_mode specifies if the path is a valid project model path or not. For example, if we are processing a metadata.parties.*, we need to know which metadata we are processing. If we pass contextual_mode=true, we can infer the root model by inspecting the file directory

                                                                            If contextual_mode=False, then the path must include the full path, e.g. catalog.metadata.parties. instead of just metadata.parties.

                                                                            When the * represents splitting a model rather than a list, the model is inspected for what parts are available, and for each new part two element paths are created, one for the parent to the current element, and another from the current element to the child.

                                                                            A path may have multiple *'s, but only the final one can represent splitting a model.

                                                                            Parameters:

                                                                            Name Type Description Default model Optional[trestle.core.base_model.OscalBaseModel]

                                                                            The OscalBaseModel being inspected to determine available elements that can be split

                                                                            required element_args List[str]

                                                                            List of str representing links in the chain of element paths to be parsed

                                                                            required relative_path Optional[pathlib.Path]

                                                                            Optional relative path (from trestle root) used to validate element args are valid.

                                                                            None

                                                                            Returns:

                                                                            Type Description List[trestle.core.models.elements.ElementPath]

                                                                            The requested parsed list of ElementPath for use in split

                                                                            Source code in trestle/core/commands/common/cmd_utils.py
                                                                            def parse_element_args(\n    model: Union[OscalBaseModel, None],\n    element_args: List[str],\n    relative_path: Optional[pathlib.Path] = None\n) -> List[ElementPath]:\n\"\"\"Parse element args into a list of ElementPath.\n\n    The element paths are either simple links of two elements, or two elements followed by *.\n    The * represents either a list of the items in that element, or a splitting of that element into its parts.\n    The only parts split off are the non-trivial ones determined by the granularity check.\n\n    contextual_mode specifies if the path is a valid project model path or not. For example,\n    if we are processing a metadata.parties.*, we need to know which metadata we are processing. If we pass\n    contextual_mode=true, we can infer the root model by inspecting the file directory\n\n    If contextual_mode=False, then the path must include the full path, e.g. catalog.metadata.parties.* instead of just\n    metadata.parties.*\n\n    When the * represents splitting a model rather than a list, the model is inspected for what parts are available,\n    and for each new part two element paths are created, one for the parent to the current element, and another from\n    the current element to the child.\n\n    A path may have multiple *'s, but only the final one can represent splitting a model.\n\n    Args:\n        model: The OscalBaseModel being inspected to determine available elements that can be split\n        element_args: List of str representing links in the chain of element paths to be parsed\n        relative_path: Optional relative path (from trestle root) used to validate element args are valid.\n    Returns:\n        The requested parsed list of ElementPath for use in split\n    \"\"\"\n    # collect all paths\n    element_paths: List[ElementPath] = []\n    for element_arg in element_args:\n        paths = parse_element_arg(model, element_arg, relative_path)\n        element_paths.extend(paths)\n\n    return element_paths\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.split_is_too_fine","title":"split_is_too_fine(split_paths, model_obj)","text":"

                                                                            Determine if the element path list goes too fine, e.g. individual strings.

                                                                            Source code in trestle/core/commands/common/cmd_utils.py
                                                                            def split_is_too_fine(split_paths: str, model_obj: OscalBaseModel) -> bool:\n\"\"\"Determine if the element path list goes too fine, e.g. individual strings.\"\"\"\n    for split_path in split_paths.split(','):\n        # find model type one level above if finishing with '.*'\n        model_type = ElementPath(split_path.rstrip('.*')).get_type(type(model_obj))\n        if model_type_is_too_granular(model_type):\n            return True\n    return False\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.cmd_utils/#trestle.core.commands.common.cmd_utils.to_model_file_name","title":"to_model_file_name(model_obj, file_prefix, content_type)","text":"

                                                                            Return the file name for the item.

                                                                            Source code in trestle/core/commands/common/cmd_utils.py
                                                                            def to_model_file_name(model_obj: OscalBaseModel, file_prefix: str, content_type: FileContentType) -> str:\n\"\"\"Return the file name for the item.\"\"\"\n    file_ext = FileContentType.to_file_extension(content_type)\n    model_type = classname_to_alias(type(model_obj).__name__, AliasMode.JSON)\n    file_name = f'{file_prefix}{const.IDX_SEP}{model_type}{file_ext}'\n    return file_name\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.return_codes/","title":"return_codes","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes","title":"trestle.core.commands.common.return_codes","text":"

                                                                            Trestle command return codes.

                                                                            "},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes","title":" CmdReturnCodes (Enum) ","text":"

                                                                            Trestle CLI return codes.

                                                                            SUCCESS - Operation/validation completed successfully COMMAND_ERROR - Generic expected error while executing command (handled by command) INCORRECT_ARGS - Provided arguments were incorrect/incomplete DOCUMENTS_VALIDATION_ERROR - Validation of the markdown or drawio files failed MODEL_VALIDATION_ERROR - Validation of OSCAL model failed TRESTLE_ROOT_ERROR - Workspace setup has failed, the root is not trestle directory IO_ERROR - IO related errors, i.e. permission issue, non-existing file, etc AUTH_ERROR - Authenication error while accessing/storing cache UNKNOWN_ERROR - Unexpected error (unhandled by command) INVALID_MODEL - Loaded model is invalid

                                                                            Source code in trestle/core/commands/common/return_codes.py
                                                                            class CmdReturnCodes(enum.Enum):\n\"\"\"\n    Trestle CLI return codes.\n\n    SUCCESS - Operation/validation completed successfully\n    COMMAND_ERROR - Generic expected error while executing command (handled by command)\n    INCORRECT_ARGS - Provided arguments were incorrect/incomplete\n    DOCUMENTS_VALIDATION_ERROR - Validation of the markdown or drawio files failed\n    MODEL_VALIDATION_ERROR - Validation of OSCAL model failed\n    TRESTLE_ROOT_ERROR - Workspace setup has failed, the root is not trestle directory\n    IO_ERROR - IO related errors, i.e. permission issue, non-existing file, etc\n    AUTH_ERROR - Authenication error while accessing/storing cache\n    UNKNOWN_ERROR - Unexpected error (unhandled by command)\n    INVALID_MODEL - Loaded model is invalid\n    \"\"\"\n\n    SUCCESS = 0\n    COMMAND_ERROR = 1\n    INCORRECT_ARGS = 2\n    DOCUMENTS_VALIDATION_ERROR = 3\n    OSCAL_VALIDATION_ERROR = 4\n    TRESTLE_ROOT_ERROR = 5\n    IO_ERROR = 6\n    AUTH_ERROR = 7\n    UNKNOWN_ERROR = 8\n
                                                                            "},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.AUTH_ERROR","title":"AUTH_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.COMMAND_ERROR","title":"COMMAND_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.DOCUMENTS_VALIDATION_ERROR","title":"DOCUMENTS_VALIDATION_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.INCORRECT_ARGS","title":"INCORRECT_ARGS","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.IO_ERROR","title":"IO_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.OSCAL_VALIDATION_ERROR","title":"OSCAL_VALIDATION_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.SUCCESS","title":"SUCCESS","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.TRESTLE_ROOT_ERROR","title":"TRESTLE_ROOT_ERROR","text":""},{"location":"api_reference/trestle.core.commands.common.return_codes/#trestle.core.commands.common.return_codes.CmdReturnCodes.UNKNOWN_ERROR","title":"UNKNOWN_ERROR","text":""},{"location":"api_reference/trestle.core.commands.create/","title":"create","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create","title":"trestle.core.commands.create","text":"

                                                                            Trestle Create CommandPlusDocs.

                                                                            "},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd","title":" CreateCmd (CommandPlusDocs) ","text":"

                                                                            Create a sample OSCAL model in trestle workspace or create new elements within a given model.

                                                                            Source code in trestle/core/commands/create.py
                                                                            class CreateCmd(CommandPlusDocs):\n\"\"\"Create a sample OSCAL model in trestle workspace or create new elements within a given model.\"\"\"\n\n    name = 'create'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-t', '--type', help='Type of model if created anew.', choices=const.MODEL_TYPE_LIST)\n        self.add_argument('-o', '--output', help='Name of the output created model.')\n        self.add_argument(const.IOF_SHORT, const.IOF_LONG, help=const.IOF_HELP, action='store_true')\n        self.add_argument(\n            '-x', '--extension', help='Type of file output.', choices=['json', 'yaml', 'yml'], default='json'\n        )\n        self.add_argument(\n            '-f', '--file', help='Optional existing OSCAL file that will have elements created within it.', type=str\n        )\n        self.add_argument(\n            '-e', '--element', help='Optional path of element to be created whithin the specified file.', type=str\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"\n        Execute the create command.\n\n        Notes\n            Either a new model will be created of the specified type,\n            or an existing file will have new elements added within it.\n        \"\"\"\n        try:\n            # Normal create path\n            if args.type and args.output:\n                object_type = ElementPath(args.type).get_type()\n                return self.create_object(args.type, object_type, args)\n            # Add path\n            elif args.file and args.element:\n                add = Add()\n                return add.add_from_args(args)\n\n            raise err.TrestleIncorrectArgsError(\n                'Create requires either a model type and output name, or a file and element path.'\n            )\n\n        except Exception as e:  # pragma: no cover\n            return err.handle_generic_command_exception(e, logger, 'Error while creating a sample OSCAL model')\n\n    @classmethod\n    def create_object(cls, model_alias: str, object_type: Type[TopLevelOscalModel], args: argparse.Namespace) -> int:\n\"\"\"Create a top level OSCAL object within the trestle directory, leveraging functionality in add.\"\"\"\n        log.set_log_level_from_args(args)\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n        if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n            raise err.TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n        desired_model_dir = trestle_root / plural_path / args.output\n\n        desired_model_path = desired_model_dir / (model_alias + '.' + args.extension)\n\n        if desired_model_path.exists():\n            raise err.TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n        # Create sample model.\n        sample_model = generators.generate_sample_model(object_type, include_optional=args.include_optional_fields)\n        # Presuming top level level model not sure how to do the typing for this.\n        sample_model.metadata.title = f'Generic {model_alias} created by trestle named {args.output}.'\n        sample_model.metadata.last_modified = datetime.now().astimezone()\n        sample_model.metadata.oscal_version = trestle.oscal.OSCAL_VERSION\n        sample_model.metadata.version = '0.0.0'\n\n        top_element = Element(sample_model, model_alias)\n\n        create_action = CreatePathAction(desired_model_path.resolve(), True)\n        write_action = WriteFileAction(\n            desired_model_path.resolve(), top_element, FileContentType.to_content_type(desired_model_path.suffix)\n        )\n\n        # create a plan to write the directory and file.\n        create_plan = Plan()\n        create_plan.add_action(create_action)\n        create_plan.add_action(write_action)\n        create_plan.execute()\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.create/#trestle.core.commands.create.CreateCmd.create_object","title":"create_object(model_alias, object_type, args) classmethod","text":"

                                                                            Create a top level OSCAL object within the trestle directory, leveraging functionality in add.

                                                                            Source code in trestle/core/commands/create.py
                                                                            @classmethod\ndef create_object(cls, model_alias: str, object_type: Type[TopLevelOscalModel], args: argparse.Namespace) -> int:\n\"\"\"Create a top level OSCAL object within the trestle directory, leveraging functionality in add.\"\"\"\n    log.set_log_level_from_args(args)\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n    if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n        raise err.TrestleRootError(f'Given directory {trestle_root} is not a trestle project.')\n\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n    desired_model_dir = trestle_root / plural_path / args.output\n\n    desired_model_path = desired_model_dir / (model_alias + '.' + args.extension)\n\n    if desired_model_path.exists():\n        raise err.TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n    # Create sample model.\n    sample_model = generators.generate_sample_model(object_type, include_optional=args.include_optional_fields)\n    # Presuming top level level model not sure how to do the typing for this.\n    sample_model.metadata.title = f'Generic {model_alias} created by trestle named {args.output}.'\n    sample_model.metadata.last_modified = datetime.now().astimezone()\n    sample_model.metadata.oscal_version = trestle.oscal.OSCAL_VERSION\n    sample_model.metadata.version = '0.0.0'\n\n    top_element = Element(sample_model, model_alias)\n\n    create_action = CreatePathAction(desired_model_path.resolve(), True)\n    write_action = WriteFileAction(\n        desired_model_path.resolve(), top_element, FileContentType.to_content_type(desired_model_path.suffix)\n    )\n\n    # create a plan to write the directory and file.\n    create_plan = Plan()\n    create_plan.add_action(create_action)\n    create_plan.add_action(write_action)\n    create_plan.execute()\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.describe/","title":"describe","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe","title":"trestle.core.commands.describe","text":"

                                                                            Trestle Describe Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd","title":" DescribeCmd (CommandPlusDocs) ","text":"

                                                                            Describe contents of a model file including optional element path.

                                                                            Source code in trestle/core/commands/describe.py
                                                                            class DescribeCmd(CommandPlusDocs):\n\"\"\"Describe contents of a model file including optional element path.\"\"\"\n\n    # The only output is via log lines.  No other results or side-effects.\n\n    name = 'describe'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument('-f', '--file', help='OSCAL file to import.', type=str, required=True)\n\n        self.add_argument(\n            '-e', '--element', help='Optional name of element in file to describe.', type=str, required=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            logger.debug('Entering trestle describe.')\n\n            log.set_log_level_from_args(args)\n\n            if args.file:\n                model_file = pathlib.Path(args.file)\n\n                element = '' if not args.element else args.element.strip(\"'\")\n                results = self.describe(model_file.resolve(), element, args.trestle_root)\n\n                return CmdReturnCodes.SUCCESS.value if len(results) > 0 else CmdReturnCodes.COMMAND_ERROR.value\n            else:\n                raise TrestleIncorrectArgsError('No file specified for command describe.')\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while describing contents of a model')\n\n    @classmethod\n    def _clean_type_string(cls, text: str) -> str:\n        text = text.replace(\"<class '\", '').replace(\"'>\", '')\n        text = text.replace('trestle.oscal.', '')\n        text = text.replace('pydantic.main.', 'stripped.')\n        return text\n\n    @classmethod\n    def _description_text(cls, sub_model: Optional[Union[OscalBaseModel, List[OscalBaseModel]]]) -> str:\n        clip_string = 100\n        if sub_model is None:\n            return 'None'\n        if type(sub_model) is list:\n            n_items = len(sub_model)\n            type_text = 'Unknown' if not n_items else f'{cls._clean_type_string(str(type(sub_model[0])))}'\n            text = f'list of {n_items} items of type {type_text}'\n            return text\n        if type(sub_model) is str:\n            return sub_model if len(sub_model\n                                    ) < clip_string else sub_model[:clip_string] + '[truncated]'  # type: ignore\n        if hasattr(sub_model, 'type_'):\n            return cls._clean_type_string(str(sub_model.type_))\n        return cls._clean_type_string(str(type(sub_model)))\n\n    @classmethod\n    def describe(cls, file_path: pathlib.Path, element_path_str: str, trestle_root: pathlib.Path) -> List[str]:\n\"\"\"Describe the contents of the file.\n\n        Args:\n            file_path: pathlib.Path Path for model file to describe.\n            element_path_str: Element path of element in model to describe.  Can be ''.\n\n        Returns:\n            The list of lines of text in the description, or an empty list on failure\n        \"\"\"\n        # figure out the model type so we can read it\n        try:\n            model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n            model: OscalBaseModel = model_type.oscal_read(file_path)\n        except TrestleError as e:\n            logger.warning(f'Error loading model {file_path} to describe: {e}')\n            return []\n\n        sub_model = model\n\n        # if an element path was provided, follow the path chain to the desired sub_model\n        if element_path_str:\n            if '*' in element_path_str or ',' in element_path_str:\n                logger.warning('Wildcards and commas are not allowed in the element path for describe.')\n                return []\n\n            if '.' not in element_path_str:\n                logger.warning('The element path for describe must either be omitted or contain at least 2 parts.')\n                return []\n\n            element_paths = utils.parse_element_arg(model, element_path_str)\n\n            sub_model_element = Element(model)\n\n            for element_path in element_paths:\n                sub_model = sub_model_element.get_at(element_path, False)\n                sub_model_element = Element(sub_model)\n\n        # now that we have the desired sub_model we can describe it\n\n        text_out: List[str] = []\n\n        # create top level text depending on whether an element path was used\n        element_text = '' if not element_path_str else f' at element path {element_path_str}'\n\n        if type(sub_model) is list:\n            text = f'Model file {file_path}{element_text} is a {cls._description_text(sub_model)}'\n            text_out.append(text)\n            logger.info(text)\n        else:\n            text = f'Model file {file_path}{element_text} is of type '\n            text += f'{cls._clean_type_string(str(type(sub_model)))} and contains:'\n            text_out.append(text)\n            logger.info(text)\n            for key in sub_model.__fields__.keys():\n                value = getattr(sub_model, key, None)\n                text = f'    {key}: {cls._description_text(value)}'\n                text_out.append(text)\n                logger.info(text)\n\n        return text_out\n
                                                                            "},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.describe/#trestle.core.commands.describe.DescribeCmd.describe","title":"describe(file_path, element_path_str, trestle_root) classmethod","text":"

                                                                            Describe the contents of the file.

                                                                            Parameters:

                                                                            Name Type Description Default file_path Path

                                                                            pathlib.Path Path for model file to describe.

                                                                            required element_path_str str

                                                                            Element path of element in model to describe. Can be ''.

                                                                            required

                                                                            Returns:

                                                                            Type Description List[str]

                                                                            The list of lines of text in the description, or an empty list on failure

                                                                            Source code in trestle/core/commands/describe.py
                                                                            @classmethod\ndef describe(cls, file_path: pathlib.Path, element_path_str: str, trestle_root: pathlib.Path) -> List[str]:\n\"\"\"Describe the contents of the file.\n\n    Args:\n        file_path: pathlib.Path Path for model file to describe.\n        element_path_str: Element path of element in model to describe.  Can be ''.\n\n    Returns:\n        The list of lines of text in the description, or an empty list on failure\n    \"\"\"\n    # figure out the model type so we can read it\n    try:\n        model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n        model: OscalBaseModel = model_type.oscal_read(file_path)\n    except TrestleError as e:\n        logger.warning(f'Error loading model {file_path} to describe: {e}')\n        return []\n\n    sub_model = model\n\n    # if an element path was provided, follow the path chain to the desired sub_model\n    if element_path_str:\n        if '*' in element_path_str or ',' in element_path_str:\n            logger.warning('Wildcards and commas are not allowed in the element path for describe.')\n            return []\n\n        if '.' not in element_path_str:\n            logger.warning('The element path for describe must either be omitted or contain at least 2 parts.')\n            return []\n\n        element_paths = utils.parse_element_arg(model, element_path_str)\n\n        sub_model_element = Element(model)\n\n        for element_path in element_paths:\n            sub_model = sub_model_element.get_at(element_path, False)\n            sub_model_element = Element(sub_model)\n\n    # now that we have the desired sub_model we can describe it\n\n    text_out: List[str] = []\n\n    # create top level text depending on whether an element path was used\n    element_text = '' if not element_path_str else f' at element path {element_path_str}'\n\n    if type(sub_model) is list:\n        text = f'Model file {file_path}{element_text} is a {cls._description_text(sub_model)}'\n        text_out.append(text)\n        logger.info(text)\n    else:\n        text = f'Model file {file_path}{element_text} is of type '\n        text += f'{cls._clean_type_string(str(type(sub_model)))} and contains:'\n        text_out.append(text)\n        logger.info(text)\n        for key in sub_model.__fields__.keys():\n            value = getattr(sub_model, key, None)\n            text = f'    {key}: {cls._description_text(value)}'\n            text_out.append(text)\n            logger.info(text)\n\n    return text_out\n
                                                                            "},{"location":"api_reference/trestle.core.commands.href/","title":"href","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href","title":"trestle.core.commands.href","text":"

                                                                            Trestle Href Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd","title":" HrefCmd (CommandPlusDocs) ","text":"

                                                                            Change href of import in profile to point to catalog in trestle workspace.

                                                                            This command is needed when generating an SSP with a profile that imports a catalog from a temporary location different from the final intended location of the catalog. Omit the href argument to see the list of current imports in the profile.

                                                                            Source code in trestle/core/commands/href.py
                                                                            class HrefCmd(CommandPlusDocs):\n\"\"\"Change href of import in profile to point to catalog in trestle workspace.\n\n    This command is needed when generating an SSP with a profile that imports a catalog from a temporary\n    location different from the final intended location of the catalog.  Omit the href argument to see\n    the list of current imports in the profile.\n    \"\"\"\n\n    name = 'href'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument(\n            '-n', '--name', help='Name of trestle profile to modify (just its name).', type=str, required=True\n        )\n\n        self.add_argument(\n            '-hr',\n            '--href',\n            help='New href of form trestle://catalogs/mycat/catalog.json.',\n            type=str,\n            required=False,\n            default=''\n        )\n\n        self.add_argument(\n            '-i',\n            '--item',\n            help='Item number of href to modify.  Get list by running href with just -n <prof_name> to list values.',\n            type=int,\n            required=False,\n            default=0\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            logger.debug('Entering trestle href.')\n\n            log.set_log_level_from_args(args)\n\n            profile_name: str = args.name\n\n            new_href: str = args.href.strip(\"'\")\n\n            item_num = args.item\n\n            return self.change_import_href(args.trestle_root, profile_name, new_href, item_num)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, f'Error while changing href or import in profile: {e}')\n\n    @classmethod\n    def change_import_href(cls, trestle_root: pathlib.Path, profile_name: str, new_href: str, import_num: int) -> int:\n\"\"\"Change the href of the import in the profile to point to a catalog in a specific location.\n\n        A Profile has an Imports list containing at least one href of a catalog or profile to be imported.\n        If the item being referenced is currently in the same trestle workspace as the main profile, the original\n        href is likely different from the one needed to access the item from the profile.  Therefore,\n        in order for trestle to find the item directly from the profile, the href must be modified in a way that\n        trestle can load it.\n\n        If the item is already at the link referred to by the href as a valid URI or absolute file path then no\n        change is needed.  But if the item is being worked on in the same trestle directory as the profile,\n        the href should be modified to something like trestle://catalogs/my_catalog/catalog.json\n\n        This change only needs to be made once to the profile while the profile is being used to generate SSP's\n        from the local item, but if the final profile is released the href would need to be changed to the\n        intended final location of the referenced item.\n\n        Args:\n            trestle_root: trestle_root for this call\n            profile_name: Name of profile already imported into trestle containing href's to be changed\n            new_href: New value for the href of the import.  If blank just list the hrefs\n            import_num: Item number of the href to change.\n\n\n        Returns:\n            0 on success, 1 on failure\n\n        Assumptions and requirements:\n            The profile must be a valid profile in the trestle workspace.\n            The import must either be a valid uri, including local file, or trestle://\n            The original href is not checked and will be overwritten.\n            If href is the empty string, just list all hrefs.\n\n        Future work:\n            Allow multiple imports with matching hrefs.\n            Allow href to point to profile in trestle rather than catalog, and by name.\n            Allow full chaining of linked catalogs and profiles.\n\n        \"\"\"\n        profile_data, profile_path = load_validate_model_name(trestle_root, profile_name, Profile)\n        n_imports = len(profile_data.imports)\n        if not new_href:\n            logger.info(f'List of imports for profile {profile_name}:')\n            for ii, import_ in enumerate(profile_data.imports):\n                logger.info(f'{ii:2}: {import_.href}')\n            return CmdReturnCodes.SUCCESS.value\n        if n_imports <= import_num:\n            raise TrestleError(f'Import number {import_num} is too large.  This profile has only {n_imports} imports.')\n\n        logger.info(f'Changing import {import_num} in profile {profile_name} from, to:')\n        logger.info(f'{profile_data.imports[import_num].href}')\n        logger.info(f'{new_href}')\n        profile_data.imports[import_num].href = new_href\n        profile_data.oscal_write(profile_path)  # type: ignore\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.href/#trestle.core.commands.href.HrefCmd.change_import_href","title":"change_import_href(trestle_root, profile_name, new_href, import_num) classmethod","text":"

                                                                            Change the href of the import in the profile to point to a catalog in a specific location.

                                                                            A Profile has an Imports list containing at least one href of a catalog or profile to be imported. If the item being referenced is currently in the same trestle workspace as the main profile, the original href is likely different from the one needed to access the item from the profile. Therefore, in order for trestle to find the item directly from the profile, the href must be modified in a way that trestle can load it.

                                                                            If the item is already at the link referred to by the href as a valid URI or absolute file path then no change is needed. But if the item is being worked on in the same trestle directory as the profile, the href should be modified to something like trestle://catalogs/my_catalog/catalog.json

                                                                            This change only needs to be made once to the profile while the profile is being used to generate SSP's from the local item, but if the final profile is released the href would need to be changed to the intended final location of the referenced item.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            trestle_root for this call

                                                                            required profile_name str

                                                                            Name of profile already imported into trestle containing href's to be changed

                                                                            required new_href str

                                                                            New value for the href of the import. If blank just list the hrefs

                                                                            required import_num int

                                                                            Item number of the href to change.

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success, 1 on failure

                                                                            Assumptions and requirements: The profile must be a valid profile in the trestle workspace. The import must either be a valid uri, including local file, or trestle:// The original href is not checked and will be overwritten. If href is the empty string, just list all hrefs.

                                                                            Future work: Allow multiple imports with matching hrefs. Allow href to point to profile in trestle rather than catalog, and by name. Allow full chaining of linked catalogs and profiles.

                                                                            Source code in trestle/core/commands/href.py
                                                                            @classmethod\ndef change_import_href(cls, trestle_root: pathlib.Path, profile_name: str, new_href: str, import_num: int) -> int:\n\"\"\"Change the href of the import in the profile to point to a catalog in a specific location.\n\n    A Profile has an Imports list containing at least one href of a catalog or profile to be imported.\n    If the item being referenced is currently in the same trestle workspace as the main profile, the original\n    href is likely different from the one needed to access the item from the profile.  Therefore,\n    in order for trestle to find the item directly from the profile, the href must be modified in a way that\n    trestle can load it.\n\n    If the item is already at the link referred to by the href as a valid URI or absolute file path then no\n    change is needed.  But if the item is being worked on in the same trestle directory as the profile,\n    the href should be modified to something like trestle://catalogs/my_catalog/catalog.json\n\n    This change only needs to be made once to the profile while the profile is being used to generate SSP's\n    from the local item, but if the final profile is released the href would need to be changed to the\n    intended final location of the referenced item.\n\n    Args:\n        trestle_root: trestle_root for this call\n        profile_name: Name of profile already imported into trestle containing href's to be changed\n        new_href: New value for the href of the import.  If blank just list the hrefs\n        import_num: Item number of the href to change.\n\n\n    Returns:\n        0 on success, 1 on failure\n\n    Assumptions and requirements:\n        The profile must be a valid profile in the trestle workspace.\n        The import must either be a valid uri, including local file, or trestle://\n        The original href is not checked and will be overwritten.\n        If href is the empty string, just list all hrefs.\n\n    Future work:\n        Allow multiple imports with matching hrefs.\n        Allow href to point to profile in trestle rather than catalog, and by name.\n        Allow full chaining of linked catalogs and profiles.\n\n    \"\"\"\n    profile_data, profile_path = load_validate_model_name(trestle_root, profile_name, Profile)\n    n_imports = len(profile_data.imports)\n    if not new_href:\n        logger.info(f'List of imports for profile {profile_name}:')\n        for ii, import_ in enumerate(profile_data.imports):\n            logger.info(f'{ii:2}: {import_.href}')\n        return CmdReturnCodes.SUCCESS.value\n    if n_imports <= import_num:\n        raise TrestleError(f'Import number {import_num} is too large.  This profile has only {n_imports} imports.')\n\n    logger.info(f'Changing import {import_num} in profile {profile_name} from, to:')\n    logger.info(f'{profile_data.imports[import_num].href}')\n    logger.info(f'{new_href}')\n    profile_data.imports[import_num].href = new_href\n    profile_data.oscal_write(profile_path)  # type: ignore\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.import_/","title":"import_","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_","title":"trestle.core.commands.import_","text":"

                                                                            Trestle Import Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_.ImportCmd","title":" ImportCmd (CommandPlusDocs) ","text":"

                                                                            Import an existing full OSCAL model into the trestle workspace.

                                                                            Source code in trestle/core/commands/import_.py
                                                                            class ImportCmd(CommandPlusDocs):\n\"\"\"Import an existing full OSCAL model into the trestle workspace.\"\"\"\n\n    name = 'import'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument(\n            '-f', '--file', help='OSCAL file to import - either file path or url.', type=str, required=True\n        )\n        self.add_argument('-o', '--output', help='Name of output element.', type=str, required=True)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Top level import run command.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            trestle_root = args.trestle_root\n            if not file_utils.is_valid_project_root(trestle_root):\n                raise TrestleRootError(f'Attempt to import from non-valid trestle project root {trestle_root}')\n\n            input_uri = args.file\n            if cache.FetcherFactory.in_trestle_directory(trestle_root, input_uri):\n                raise TrestleError(\n                    f'Imported file {input_uri} cannot be from current trestle project. Use duplicate instead.'\n                )\n\n            content_type = FileContentType.to_content_type('.' + input_uri.split('.')[-1])\n\n            fetcher = cache.FetcherFactory.get_fetcher(trestle_root, str(input_uri))\n\n            model_read, parent_alias = fetcher.get_oscal(True)\n\n            # validate the loaded model in memory before writing out\n            # this will do any needed fixes to the file, such as assign missing catalog group ids\n            args_validate = argparse.Namespace(mode=const.VAL_MODE_ALL)\n            validator: Validator = validator_factory.get(args_validate)\n            if not validator.model_is_valid(model_read, True, trestle_root):  # type: ignore\n                logger.warning(f'Validation of file to be imported {input_uri} did not pass.  Import failed.')\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n            plural_path = ModelUtils.model_type_to_model_dir(parent_alias)\n\n            output_name = args.output\n\n            desired_model_dir = trestle_root / plural_path\n            desired_model_path: pathlib.Path = desired_model_dir / output_name / parent_alias\n            desired_model_path = desired_model_path.with_suffix(FileContentType.to_file_extension(content_type)\n                                                                ).resolve()\n\n            if desired_model_path.exists():\n                logger.warning(f'Cannot import because file to be imported here: {desired_model_path} already exists.')\n                return CmdReturnCodes.COMMAND_ERROR.value\n\n            if args.regenerate:\n                logger.debug(f'regenerating uuids in imported file {input_uri}')\n                model_read, lut, nchanged = ModelUtils.regenerate_uuids(model_read)\n                logger.debug(f'uuid lut has {len(lut.items())} entries and {nchanged} refs were updated')\n\n            top_element = Element(model_read)\n            create_action = CreatePathAction(desired_model_path, True)\n            write_action = WriteFileAction(desired_model_path, top_element, content_type)\n\n            # create a plan to create the directory and write the imported file.\n            import_plan = Plan()\n            import_plan.add_action(create_action)\n            import_plan.add_action(write_action)\n\n            import_plan.execute()\n\n            args = argparse.Namespace(\n                file=desired_model_path,\n                verbose=args.verbose,\n                trestle_root=args.trestle_root,\n                type=None,\n                all=None,\n                quiet=True\n            )\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while importing OSCAL file')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.import_/#trestle.core.commands.import_.ImportCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.init/","title":"init","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init","title":"trestle.core.commands.init","text":"

                                                                            Trestle Init Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init.InitCmd","title":" InitCmd (CommandBase) ","text":"

                                                                            Initialize a trestle working directory.

                                                                            Source code in trestle/core/commands/init.py
                                                                            class InitCmd(CommandBase):\n\"\"\"Initialize a trestle working directory.\"\"\"\n\n    name = 'init'\n\n    def _init_arguments(self) -> None:\n\n        self.add_argument(const.INIT_FULL_SHORT, const.INIT_FULL_LONG, help=const.INIT_FULL_HELP, action='store_true')\n        self.add_argument(\n            const.INIT_LOCAL_SHORT, const.INIT_LOCAL_LONG, help=const.INIT_LOCAL_HELP, action='store_true'\n        )\n        self.add_argument(\n            const.INIT_GOVDOCS_SHORT, const.INIT_GOVDOCS_LONG, help=const.INIT_GOVDOCS_HELP, action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Create a trestle workspace in the current directory.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            dir_path: pathlib.Path = args.trestle_root\n            if not dir_path.exists() or not dir_path.is_dir():\n                raise TrestleRootError(\n                    f'Initialization failed. Given directory {dir_path} does not exist or is not a directory.'\n                )\n\n            if not (args.full or args.local or args.govdocs):\n                # Running in full mode by default\n                args.full = True\n\n            init_dist_folder = True if args.full else False\n            init_oscal_folders = True if args.local or args.full else False\n            copy_config_file = True if args.full or args.local else False\n\n            self._create_directories(dir_path, init_oscal_folders, init_dist_folder)\n\n            if copy_config_file:\n                self._copy_config_file(dir_path)\n\n            logger.info(f'Initialized trestle project successfully in {dir_path}')\n\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Failed to initialize Trestle working directory.')\n\n    def _create_directories(self, root: pathlib.Path, create_model_folders: bool, create_dist_folder: bool) -> None:\n\"\"\"Create the directory tree if it does not exist.\"\"\"\n        # Prepare directory list to be created\n        try:\n            directory_list = [root / pathlib.Path(const.TRESTLE_CONFIG_DIR)]\n\n            if create_model_folders:\n                for model_dir in const.MODEL_DIR_LIST:\n                    directory_list.append(root / pathlib.Path(model_dir))\n                    if create_dist_folder:\n                        directory_list.append(root / pathlib.Path(const.TRESTLE_DIST_DIR) / model_dir)\n\n            # Create directories\n            for directory in directory_list:\n                directory.mkdir(parents=True, exist_ok=True)\n                file_path = pathlib.Path(directory) / const.TRESTLE_KEEP_FILE\n                file_utils.make_hidden_file(file_path)\n        except OSError as e:\n            raise TrestleError(f'Error while creating directories: {e}')\n        except Exception as e:\n            raise TrestleError(f'Unexpected error while creating directories: {e}')\n\n    def _copy_config_file(self, root: pathlib.Path) -> None:\n\"\"\"Copy the initial config.ini file to .trestle directory.\"\"\"\n        try:\n            ref = importlib_resources.files('trestle.resources') / const.TRESTLE_CONFIG_FILE\n            with importlib_resources.as_file(ref) as source_path:\n                destination_path = (root / pathlib.Path(const.TRESTLE_CONFIG_DIR) / const.TRESTLE_CONFIG_FILE).resolve()\n                copyfile(source_path, destination_path)\n\n        except (shutil.SameFileError, OSError) as e:\n            raise TrestleError(f'Error while copying config file: {e}')\n        except Exception as e:\n            raise TrestleError(f'Unexpected error while copying config file: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.init/#trestle.core.commands.init.InitCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.merge/","title":"merge","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge","title":"trestle.core.commands.merge","text":"

                                                                            Trestle Merge Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.trace","title":"trace","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd","title":" MergeCmd (CommandPlusDocs) ","text":"

                                                                            Merge subcomponents on a trestle model.

                                                                            Source code in trestle/core/commands/merge.py
                                                                            class MergeCmd(CommandPlusDocs):\n\"\"\"Merge subcomponents on a trestle model.\"\"\"\n\n    name = 'merge'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=f'{const.ARG_DESC_ELEMENT}(s) to be merged. The last element is merged into the second last element.',\n            required=True\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Merge elements into the parent oscal model.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n\n            # remove any quotes passed in as on windows platforms\n            elements_clean = args.element.strip(\"'\")\n            element_paths = elements_clean.split(',')\n            trace.log(f'merge _run element paths {element_paths}')\n            cwd = Path.cwd()\n            rc = self.perform_all_merges(element_paths, cwd, args.trestle_root)\n            return rc\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while merging subcomponents on a trestle model')\n\n    @classmethod\n    def perform_all_merges(cls, element_paths: List[str], effective_cwd: Path, trestle_root: Path) -> int:\n\"\"\"Run all merges over a list of element paths.\"\"\"\n        for element_path in element_paths:\n            logger.debug(f'merge {element_path}')\n            plan = cls.merge(effective_cwd, ElementPath(element_path), trestle_root)\n            plan.execute()\n        return CmdReturnCodes.SUCCESS.value\n\n    @classmethod\n    def merge(cls, effective_cwd: Path, element_path: ElementPath, trestle_root: Path) -> Plan:\n\"\"\"Merge operations.\n\n        It returns a plan for the operation\n        \"\"\"\n        if not element_path.is_multipart():\n            raise TrestleError(\n                'Multiple parts of an element path must be passed to merge e.g. catalog.* or catalog.groups'\n            )\n\n        target_model_alias = element_path.get_last()\n        logger.debug(f'merge element path list: {element_path} target model alias {target_model_alias}')\n        # 1. Load desination model into a stripped model\n        # Load destination model\n        destination_path = element_path.get_preceding_path()\n        destination_model_alias = destination_path.get_last()\n        trace.log(f'merge destination model alias: {destination_model_alias}')\n        trace.log('merge getting contextual file type effective working directory')\n        # Destination model filetype\n        file_type = file_utils.get_contextual_file_type(effective_cwd)\n        trace.log(f'contextual file type is {file_type}')\n\n        file_ext = FileContentType.to_file_extension(file_type)\n        # Destination model filename\n        destination_model_path = (\n            effective_cwd / f'{classname_to_alias(destination_model_alias, AliasMode.JSON)}{file_ext}'\n        )\n        trace.log(f'destination model filename is {destination_model_path}')\n        destination_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root)\n\n        destination_model_object: OscalBaseModel = None\n        if destination_model_path.exists():\n            trace.log('dest filename exists so read it')\n            destination_model_object = destination_model_type.oscal_read(destination_model_path)\n        # 2. If target is wildcard, load distributed destination model and replace destination model.\n        # Handle WILDCARD '*' match. Return plan to load the destination model, with its distributed attributes\n        if target_model_alias == '*':\n            trace.log('handle target model alias wildcard')\n            collection_type = None\n            if destination_model_type.is_collection_container():\n                collection_type = destination_model_type.get_collection_type()\n\n            merged_model_type, _, merged_model_instance = ModelUtils.load_distributed(\n                destination_model_path, trestle_root, collection_type)\n            plan = Plan()\n            reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n            wrapper_alias = destination_model_alias\n            write_destination_action = WriteFileAction(\n                destination_model_path, Element(merged_model_instance, wrapper_alias), content_type=file_type\n            )\n            remove_path_folder = effective_cwd / destination_model_alias\n            delete_target_action = RemovePathAction(remove_path_folder)\n            plan: Plan = Plan()\n            plan.add_action(reset_destination_action)\n            plan.add_action(write_destination_action)\n            plan.add_action(delete_target_action)\n            return plan\n\n        trace.log(f'get dest model with fields stripped: {target_model_alias}')\n        # Get destination model without the target field stripped\n        merged_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root,\n                                                                  aliases_not_to_be_stripped=[target_model_alias])\n        # 3. Load Target model. Target model could be stripped\n        try:\n            target_model_type = element_path.get_type(merged_model_type)\n        except Exception as e:\n            logger.debug(f'target model not found, element path list {element_path} type {merged_model_type}')\n            raise TrestleError(\n                f'Target model not found. Possibly merge of the elements not allowed at this point. {str(e)}'\n            )\n        target_model_path = effective_cwd / destination_model_alias\n        trace.log(f'look for target model path {target_model_path} at dest alias {destination_model_alias} rel to cwd')\n\n        # target_model filename - depends whether destination model is decomposed or not\n        if target_model_path.exists():\n            trace.log(f'target model path does exist so target path is subdir with target alias {target_model_alias}')\n            target_model_path = target_model_path / target_model_alias\n        else:\n            trace.log(f'target model filename does not exist so target path is target alias {target_model_alias}')\n            target_model_path = target_model_path / target_model_alias  # FIXME this is same as above\n        trace.log(f'final target model path is {target_model_path}')\n\n        # if target model is a file then handle file. If file doesn't exist, handle the directory,\n        # but in this case it's a list or a dict collection type\n        target_model_filename = target_model_path.with_suffix(file_ext)\n        if target_model_filename.exists():\n            trace.log(f'target model path with extension does exist so load distrib {target_model_filename}')\n            _, _, target_model_object = ModelUtils.load_distributed(target_model_filename, trestle_root)\n        else:\n            target_model_filename = Path(target_model_path)\n            trace.log(f'target model path plus extension does not exist so load distrib {target_model_filename}')\n            trace.log(f'get collection type for model type {target_model_type}')\n            collection_type = type_utils.get_origin(target_model_type)\n            trace.log(f'load {target_model_filename} as collection type {collection_type}')\n            _, _, target_model_object = ModelUtils.load_distributed(target_model_filename,\n                                                                    trestle_root, collection_type)\n\n        if hasattr(target_model_object, '__dict__') and '__root__' in target_model_object.__dict__:\n            trace.log('loaded object has dict and root so set target model object to root contents')\n            target_model_object = target_model_object.__dict__['__root__']\n        # 4. Insert target model into destination model.\n        merged_dict = {}\n        if destination_model_object is not None:\n            merged_dict = destination_model_object.__dict__\n        merged_dict[target_model_alias] = target_model_object\n        merged_model_object = merged_model_type(**merged_dict)\n        merged_destination_element = Element(merged_model_object)\n        # 5. Create action  plan\n        trace.log(f'create path action clear content: {destination_model_path}')\n        reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n        trace.log(f'write file action {destination_model_path}')\n        write_destination_action = WriteFileAction(\n            destination_model_path, merged_destination_element, content_type=file_type\n        )\n        # FIXME this will delete metadata.json but it will leave metadata/roles/roles.*\n        # need to clean up all lower dirs\n        trace.log(f'remove path action {target_model_filename}')\n        delete_target_action = RemovePathAction(target_model_filename)\n\n        plan: Plan = Plan()\n        plan.add_action(reset_destination_action)\n        plan.add_action(write_destination_action)\n        plan.add_action(delete_target_action)\n\n        # TODO: Destination model directory is empty or already merged? Then clean up.\n\n        return plan\n
                                                                            "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd.merge","title":"merge(effective_cwd, element_path, trestle_root) classmethod","text":"

                                                                            Merge operations.

                                                                            It returns a plan for the operation

                                                                            Source code in trestle/core/commands/merge.py
                                                                            @classmethod\ndef merge(cls, effective_cwd: Path, element_path: ElementPath, trestle_root: Path) -> Plan:\n\"\"\"Merge operations.\n\n    It returns a plan for the operation\n    \"\"\"\n    if not element_path.is_multipart():\n        raise TrestleError(\n            'Multiple parts of an element path must be passed to merge e.g. catalog.* or catalog.groups'\n        )\n\n    target_model_alias = element_path.get_last()\n    logger.debug(f'merge element path list: {element_path} target model alias {target_model_alias}')\n    # 1. Load desination model into a stripped model\n    # Load destination model\n    destination_path = element_path.get_preceding_path()\n    destination_model_alias = destination_path.get_last()\n    trace.log(f'merge destination model alias: {destination_model_alias}')\n    trace.log('merge getting contextual file type effective working directory')\n    # Destination model filetype\n    file_type = file_utils.get_contextual_file_type(effective_cwd)\n    trace.log(f'contextual file type is {file_type}')\n\n    file_ext = FileContentType.to_file_extension(file_type)\n    # Destination model filename\n    destination_model_path = (\n        effective_cwd / f'{classname_to_alias(destination_model_alias, AliasMode.JSON)}{file_ext}'\n    )\n    trace.log(f'destination model filename is {destination_model_path}')\n    destination_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root)\n\n    destination_model_object: OscalBaseModel = None\n    if destination_model_path.exists():\n        trace.log('dest filename exists so read it')\n        destination_model_object = destination_model_type.oscal_read(destination_model_path)\n    # 2. If target is wildcard, load distributed destination model and replace destination model.\n    # Handle WILDCARD '*' match. Return plan to load the destination model, with its distributed attributes\n    if target_model_alias == '*':\n        trace.log('handle target model alias wildcard')\n        collection_type = None\n        if destination_model_type.is_collection_container():\n            collection_type = destination_model_type.get_collection_type()\n\n        merged_model_type, _, merged_model_instance = ModelUtils.load_distributed(\n            destination_model_path, trestle_root, collection_type)\n        plan = Plan()\n        reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n        wrapper_alias = destination_model_alias\n        write_destination_action = WriteFileAction(\n            destination_model_path, Element(merged_model_instance, wrapper_alias), content_type=file_type\n        )\n        remove_path_folder = effective_cwd / destination_model_alias\n        delete_target_action = RemovePathAction(remove_path_folder)\n        plan: Plan = Plan()\n        plan.add_action(reset_destination_action)\n        plan.add_action(write_destination_action)\n        plan.add_action(delete_target_action)\n        return plan\n\n    trace.log(f'get dest model with fields stripped: {target_model_alias}')\n    # Get destination model without the target field stripped\n    merged_model_type, _ = ModelUtils.get_stripped_model_type(destination_model_path, trestle_root,\n                                                              aliases_not_to_be_stripped=[target_model_alias])\n    # 3. Load Target model. Target model could be stripped\n    try:\n        target_model_type = element_path.get_type(merged_model_type)\n    except Exception as e:\n        logger.debug(f'target model not found, element path list {element_path} type {merged_model_type}')\n        raise TrestleError(\n            f'Target model not found. Possibly merge of the elements not allowed at this point. {str(e)}'\n        )\n    target_model_path = effective_cwd / destination_model_alias\n    trace.log(f'look for target model path {target_model_path} at dest alias {destination_model_alias} rel to cwd')\n\n    # target_model filename - depends whether destination model is decomposed or not\n    if target_model_path.exists():\n        trace.log(f'target model path does exist so target path is subdir with target alias {target_model_alias}')\n        target_model_path = target_model_path / target_model_alias\n    else:\n        trace.log(f'target model filename does not exist so target path is target alias {target_model_alias}')\n        target_model_path = target_model_path / target_model_alias  # FIXME this is same as above\n    trace.log(f'final target model path is {target_model_path}')\n\n    # if target model is a file then handle file. If file doesn't exist, handle the directory,\n    # but in this case it's a list or a dict collection type\n    target_model_filename = target_model_path.with_suffix(file_ext)\n    if target_model_filename.exists():\n        trace.log(f'target model path with extension does exist so load distrib {target_model_filename}')\n        _, _, target_model_object = ModelUtils.load_distributed(target_model_filename, trestle_root)\n    else:\n        target_model_filename = Path(target_model_path)\n        trace.log(f'target model path plus extension does not exist so load distrib {target_model_filename}')\n        trace.log(f'get collection type for model type {target_model_type}')\n        collection_type = type_utils.get_origin(target_model_type)\n        trace.log(f'load {target_model_filename} as collection type {collection_type}')\n        _, _, target_model_object = ModelUtils.load_distributed(target_model_filename,\n                                                                trestle_root, collection_type)\n\n    if hasattr(target_model_object, '__dict__') and '__root__' in target_model_object.__dict__:\n        trace.log('loaded object has dict and root so set target model object to root contents')\n        target_model_object = target_model_object.__dict__['__root__']\n    # 4. Insert target model into destination model.\n    merged_dict = {}\n    if destination_model_object is not None:\n        merged_dict = destination_model_object.__dict__\n    merged_dict[target_model_alias] = target_model_object\n    merged_model_object = merged_model_type(**merged_dict)\n    merged_destination_element = Element(merged_model_object)\n    # 5. Create action  plan\n    trace.log(f'create path action clear content: {destination_model_path}')\n    reset_destination_action = CreatePathAction(destination_model_path, clear_content=True)\n    trace.log(f'write file action {destination_model_path}')\n    write_destination_action = WriteFileAction(\n        destination_model_path, merged_destination_element, content_type=file_type\n    )\n    # FIXME this will delete metadata.json but it will leave metadata/roles/roles.*\n    # need to clean up all lower dirs\n    trace.log(f'remove path action {target_model_filename}')\n    delete_target_action = RemovePathAction(target_model_filename)\n\n    plan: Plan = Plan()\n    plan.add_action(reset_destination_action)\n    plan.add_action(write_destination_action)\n    plan.add_action(delete_target_action)\n\n    # TODO: Destination model directory is empty or already merged? Then clean up.\n\n    return plan\n
                                                                            "},{"location":"api_reference/trestle.core.commands.merge/#trestle.core.commands.merge.MergeCmd.perform_all_merges","title":"perform_all_merges(element_paths, effective_cwd, trestle_root) classmethod","text":"

                                                                            Run all merges over a list of element paths.

                                                                            Source code in trestle/core/commands/merge.py
                                                                            @classmethod\ndef perform_all_merges(cls, element_paths: List[str], effective_cwd: Path, trestle_root: Path) -> int:\n\"\"\"Run all merges over a list of element paths.\"\"\"\n    for element_path in element_paths:\n        logger.debug(f'merge {element_path}')\n        plan = cls.merge(effective_cwd, ElementPath(element_path), trestle_root)\n        plan.execute()\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.partial_object_validate/","title":"partial_object_validate","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate","title":"trestle.core.commands.partial_object_validate","text":"

                                                                            Trestle schema-validate command.

                                                                            "},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate","title":" PartialObjectValidate (CommandBase) ","text":"

                                                                            Direct validation any oscal object in a file, including list objects.

                                                                            Source code in trestle/core/commands/partial_object_validate.py
                                                                            class PartialObjectValidate(CommandBase):\n\"\"\"Direct validation any oscal object in a file, including list objects.\"\"\"\n\n    name = 'partial-object-validate'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_FILE_SHORT}',\n            f'--{const.ARG_FILE}',\n            help=const.ARG_DESC_FILE + ' to validate',\n            required=True,\n            type=pathlib.Path\n        )\n\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=const.ARG_DESC_ELEMENT + ' to validate.',\n            required=True\n        )\n\n        self.add_argument(\n            '-nv', '--no-validators', help='Only perform the most basic validation of the file', action='store_true'\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n            file_path: pathlib.Path = args.file.resolve()\n            if not file_path.exists() or not file_path.is_file():\n                raise TrestleError('File path provided does not exist or is a directory')\n\n            element_str: str = args.element\n            if ',' in element_str:\n                logger.warning('Only a single element path is allowed.')\n\n            return self.partial_object_validate(file_path, element_str)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while validating OSCAL file')\n\n    @classmethod\n    def partial_object_validate(cls, file_path: pathlib.Path, element_string: str) -> int:\n\"\"\"Run a schema validation on a file inferring file type based on element string.\"\"\"\n        # get model type\n        logger.info(f'Validating {file_path}')\n        element_path = elements.ElementPath(element_string)\n        # get a wrapped object\n        obm_type = element_path.get_obm_wrapped_type()\n        obm_type.oscal_read(file_path)\n\n        logger.info(f'VALID: {file_path} for {element_string}')\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.partial_object_validate/#trestle.core.commands.partial_object_validate.PartialObjectValidate.partial_object_validate","title":"partial_object_validate(file_path, element_string) classmethod","text":"

                                                                            Run a schema validation on a file inferring file type based on element string.

                                                                            Source code in trestle/core/commands/partial_object_validate.py
                                                                            @classmethod\ndef partial_object_validate(cls, file_path: pathlib.Path, element_string: str) -> int:\n\"\"\"Run a schema validation on a file inferring file type based on element string.\"\"\"\n    # get model type\n    logger.info(f'Validating {file_path}')\n    element_path = elements.ElementPath(element_string)\n    # get a wrapped object\n    obm_type = element_path.get_obm_wrapped_type()\n    obm_type.oscal_read(file_path)\n\n    logger.info(f'VALID: {file_path} for {element_string}')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.remove/","title":"remove","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove","title":"trestle.core.commands.remove","text":"

                                                                            Trestle Remove Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd","title":" RemoveCmd (CommandPlusDocs) ","text":"

                                                                            Remove a subcomponent from an existing model.

                                                                            Source code in trestle/core/commands/remove.py
                                                                            class RemoveCmd(CommandPlusDocs):\n\"\"\"Remove a subcomponent from an existing model.\"\"\"\n\n    name = 'remove'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_FILE_SHORT}',\n            f'--{const.ARG_FILE}',\n            help=const.ARG_DESC_FILE + ' to remove component/subcomponent to.',\n            required=True\n        )\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=const.ARG_DESC_ELEMENT + ' to remove.',\n            required=True\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Remove an OSCAL component/subcomponent to the specified component.\n\n        This method takes input a filename and a list of comma-seperated element path. Element paths are field aliases.\n        The method first finds the parent model from the file and loads the file into the model.\n        Then the method executes 'remove' for each of the element paths specified.\n        \"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            args_dict = args.__dict__\n\n            file_path = pathlib.Path(args_dict[const.ARG_FILE]).resolve()\n            relative_path = file_path.relative_to(args.trestle_root)\n            # Get parent model and then load json into parent model\n            parent_model, parent_alias = ModelUtils.get_relative_model_type(relative_path)\n\n            parent_object = parent_model.oscal_read(file_path)\n            parent_element = Element(parent_object, parent_alias)\n\n            add_plan = Plan()\n\n            # Do _remove for each element_path specified in args\n            element_paths: List[str] = str(args_dict[const.ARG_ELEMENT]).split(',')\n            for elm_path_str in element_paths:\n                element_path = ElementPath(elm_path_str)\n                remove_action, parent_element = self.remove(element_path, parent_element)\n                add_plan.add_action(remove_action)\n\n            create_action = CreatePathAction(file_path, True)\n            write_action = WriteFileAction(file_path, parent_element, FileContentType.to_content_type(file_path.suffix))\n            add_plan.add_action(remove_action)\n            add_plan.add_action(create_action)\n            add_plan.add_action(write_action)\n\n            add_plan.execute()\n\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:\n            return err.handle_generic_command_exception(e, logger, 'Error while removing OSCAL component')\n\n    @classmethod\n    def remove(cls, element_path: ElementPath, parent_element: Element) -> Tuple[RemoveAction, Element]:\n\"\"\"For the element_path, remove a model from the parent_element of a given parent_model.\n\n        First we check if there is an existing element at that path\n        If not, we complain.\n        Then we set up an action plan to update the model (specified by file_path) in memory,\n        return the action and return the parent_element.\n\n        LIMITATIONS:\n        1. This does not remove elements of a list or dict. Instead, the entire list or dict is removed.\n        2. This cannot remove arbitrarily named elements that are not specified in the schema.\n        For example, \"responsible-parties\" contains named elements, e.g., \"organisation\". The tool will not\n        remove the \"organisation\" as it is not in the schema, but one can remove its elements, e.g., \"party-uuids\".\n        \"\"\"\n        element_path_list = element_path.get_full_path_parts()\n        if '*' in element_path_list:\n            raise err.TrestleError('trestle remove does not support Wildcard element path.')\n\n        deleting_element = parent_element.get_at(element_path)\n\n        if deleting_element is not None:\n            # The element already exists\n            if type(deleting_element) is list:\n                logger.warning(\n                    'Warning: trestle remove does not support removing elements of a list: '\n                    'this removes the entire list'\n                )\n            elif type(deleting_element) is dict:\n                logger.warning(\n                    'Warning: trestle remove does not support removing dict elements: '\n                    'this removes the entire dict element'\n                )\n        else:\n            raise err.TrestleError(f'Bad element path: {str(element_path)}')\n\n        remove_action = RemoveAction(parent_element, element_path)\n\n        return remove_action, parent_element\n
                                                                            "},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.remove/#trestle.core.commands.remove.RemoveCmd.remove","title":"remove(element_path, parent_element) classmethod","text":"

                                                                            For the element_path, remove a model from the parent_element of a given parent_model.

                                                                            First we check if there is an existing element at that path If not, we complain. Then we set up an action plan to update the model (specified by file_path) in memory, return the action and return the parent_element.

                                                                            LIMITATIONS: 1. This does not remove elements of a list or dict. Instead, the entire list or dict is removed. 2. This cannot remove arbitrarily named elements that are not specified in the schema. For example, \"responsible-parties\" contains named elements, e.g., \"organisation\". The tool will not remove the \"organisation\" as it is not in the schema, but one can remove its elements, e.g., \"party-uuids\".

                                                                            Source code in trestle/core/commands/remove.py
                                                                            @classmethod\ndef remove(cls, element_path: ElementPath, parent_element: Element) -> Tuple[RemoveAction, Element]:\n\"\"\"For the element_path, remove a model from the parent_element of a given parent_model.\n\n    First we check if there is an existing element at that path\n    If not, we complain.\n    Then we set up an action plan to update the model (specified by file_path) in memory,\n    return the action and return the parent_element.\n\n    LIMITATIONS:\n    1. This does not remove elements of a list or dict. Instead, the entire list or dict is removed.\n    2. This cannot remove arbitrarily named elements that are not specified in the schema.\n    For example, \"responsible-parties\" contains named elements, e.g., \"organisation\". The tool will not\n    remove the \"organisation\" as it is not in the schema, but one can remove its elements, e.g., \"party-uuids\".\n    \"\"\"\n    element_path_list = element_path.get_full_path_parts()\n    if '*' in element_path_list:\n        raise err.TrestleError('trestle remove does not support Wildcard element path.')\n\n    deleting_element = parent_element.get_at(element_path)\n\n    if deleting_element is not None:\n        # The element already exists\n        if type(deleting_element) is list:\n            logger.warning(\n                'Warning: trestle remove does not support removing elements of a list: '\n                'this removes the entire list'\n            )\n        elif type(deleting_element) is dict:\n            logger.warning(\n                'Warning: trestle remove does not support removing dict elements: '\n                'this removes the entire dict element'\n            )\n    else:\n        raise err.TrestleError(f'Bad element path: {str(element_path)}')\n\n    remove_action = RemoveAction(parent_element, element_path)\n\n    return remove_action, parent_element\n
                                                                            "},{"location":"api_reference/trestle.core.commands.replicate/","title":"replicate","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate","title":"trestle.core.commands.replicate","text":"

                                                                            Trestle Replicate Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd","title":" ReplicateCmd (CommandPlusDocs) ","text":"

                                                                            Replicate a top level model within the trestle directory structure.

                                                                            Source code in trestle/core/commands/replicate.py
                                                                            class ReplicateCmd(CommandPlusDocs):\n\"\"\"Replicate a top level model within the trestle directory structure.\"\"\"\n\n    name = 'replicate'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n\n        self.add_argument('model', help='Choose OSCAL model', choices=const.MODEL_TYPE_LIST)\n        self.add_argument('-n', '--name', help='Name of model to replicate.', type=str, required=True)\n        self.add_argument('-o', '--output', help='Name of replicated model.', type=str, required=True)\n        self.add_argument('-r', '--regenerate', action='store_true', help=const.HELP_REGENERATE)\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Execute and process the args.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            return self.replicate_object(args.model, args)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while replicating model')\n\n    @classmethod\n    def replicate_object(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"\n        Core replicate routine invoked by subcommands.\n\n        Args:\n            model_alias: Name of the top level model in the trestle directory.\n            args: CLI arguments\n        Returns:\n            A return code that can be used as standard posix codes. 0 is success.\n        \"\"\"\n        logger.debug('Entering replicate_object.')\n\n        # 1 Bad working directory if not running from current working directory\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n        if not trestle_root or not file_utils.is_valid_project_root(trestle_root):\n            raise TrestleError(f'Given directory: {trestle_root} is not a trestle project.')\n\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n        # 2 Check that input file given exists.\n\n        input_file_stem = trestle_root / plural_path / args.name / model_alias\n        content_type = FileContentType.path_to_content_type(input_file_stem)\n        if content_type == FileContentType.UNKNOWN:\n            raise TrestleError(\n                f'Input file {args.name} has no json or yaml file at expected location {input_file_stem}.'\n            )\n\n        input_file = input_file_stem.with_suffix(FileContentType.to_file_extension(content_type))\n\n        # 3 Distributed load from file\n        _, model_alias, model_instance = ModelUtils.load_distributed(input_file, trestle_root)\n\n        rep_model_path = trestle_root / plural_path / args.output / (\n            model_alias + FileContentType.to_file_extension(content_type)\n        )\n\n        if rep_model_path.exists():\n            raise TrestleError(f'OSCAL file to be replicated here: {rep_model_path} exists.')\n\n        if args.regenerate:\n            logger.debug(f'regenerating uuids for model {input_file}')\n            model_instance, uuid_lut, n_refs_updated = ModelUtils.regenerate_uuids(model_instance)\n            logger.debug(f'{len(uuid_lut)} uuids generated and {n_refs_updated} references updated')\n\n        # 4 Prepare actions and plan\n        top_element = Element(model_instance)\n        create_action = CreatePathAction(rep_model_path, True)\n        write_action = WriteFileAction(rep_model_path, top_element, content_type)\n\n        # create a plan to create the directory and imported file.\n        replicate_plan = Plan()\n        replicate_plan.add_action(create_action)\n        replicate_plan.add_action(write_action)\n\n        replicate_plan.execute()\n\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.replicate/#trestle.core.commands.replicate.ReplicateCmd.replicate_object","title":"replicate_object(model_alias, args) classmethod","text":"

                                                                            Core replicate routine invoked by subcommands.

                                                                            Parameters:

                                                                            Name Type Description Default model_alias str

                                                                            Name of the top level model in the trestle directory.

                                                                            required args Namespace

                                                                            CLI arguments

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            A return code that can be used as standard posix codes. 0 is success.

                                                                            Source code in trestle/core/commands/replicate.py
                                                                            @classmethod\ndef replicate_object(cls, model_alias: str, args: argparse.Namespace) -> int:\n\"\"\"\n    Core replicate routine invoked by subcommands.\n\n    Args:\n        model_alias: Name of the top level model in the trestle directory.\n        args: CLI arguments\n    Returns:\n        A return code that can be used as standard posix codes. 0 is success.\n    \"\"\"\n    logger.debug('Entering replicate_object.')\n\n    # 1 Bad working directory if not running from current working directory\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n    if not trestle_root or not file_utils.is_valid_project_root(trestle_root):\n        raise TrestleError(f'Given directory: {trestle_root} is not a trestle project.')\n\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n    # 2 Check that input file given exists.\n\n    input_file_stem = trestle_root / plural_path / args.name / model_alias\n    content_type = FileContentType.path_to_content_type(input_file_stem)\n    if content_type == FileContentType.UNKNOWN:\n        raise TrestleError(\n            f'Input file {args.name} has no json or yaml file at expected location {input_file_stem}.'\n        )\n\n    input_file = input_file_stem.with_suffix(FileContentType.to_file_extension(content_type))\n\n    # 3 Distributed load from file\n    _, model_alias, model_instance = ModelUtils.load_distributed(input_file, trestle_root)\n\n    rep_model_path = trestle_root / plural_path / args.output / (\n        model_alias + FileContentType.to_file_extension(content_type)\n    )\n\n    if rep_model_path.exists():\n        raise TrestleError(f'OSCAL file to be replicated here: {rep_model_path} exists.')\n\n    if args.regenerate:\n        logger.debug(f'regenerating uuids for model {input_file}')\n        model_instance, uuid_lut, n_refs_updated = ModelUtils.regenerate_uuids(model_instance)\n        logger.debug(f'{len(uuid_lut)} uuids generated and {n_refs_updated} references updated')\n\n    # 4 Prepare actions and plan\n    top_element = Element(model_instance)\n    create_action = CreatePathAction(rep_model_path, True)\n    write_action = WriteFileAction(rep_model_path, top_element, content_type)\n\n    # create a plan to create the directory and imported file.\n    replicate_plan = Plan()\n    replicate_plan.add_action(create_action)\n    replicate_plan.add_action(write_action)\n\n    replicate_plan.execute()\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/","title":"split","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split","title":"trestle.core.commands.split","text":"

                                                                            Trestle Split Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.trace","title":"trace","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker","title":" AliasTracker (TrestleBaseModel) pydantic-model","text":"

                                                                            Convenience class to track writing out of models.

                                                                            Source code in trestle/core/commands/split.py
                                                                            class AliasTracker(TrestleBaseModel):\n\"\"\"Convenience class to track writing out of models.\"\"\"\n\n    # This tracks the parts that need to be split from each element\n    # and makes sure it is written out once\n\n    aliases: List[str]\n    written: bool = False\n\n    def add_alias(self, alias: str) -> None:\n\"\"\"Add alias.\"\"\"\n        if alias not in self.aliases:\n            self.aliases.append(alias)\n\n    def get_aliases(self) -> List[str]:\n\"\"\"Get the list of aliases.\"\"\"\n        return self.aliases\n\n    def needs_writing(self) -> bool:\n\"\"\"Need to write the model.\"\"\"\n        return not self.written\n\n    def mark_written(self) -> None:\n\"\"\"Mark this model as written.\"\"\"\n        self.written = True\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.aliases","title":"aliases: List[str] pydantic-field required","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.written","title":"written: bool pydantic-field","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.add_alias","title":"add_alias(self, alias)","text":"

                                                                            Add alias.

                                                                            Source code in trestle/core/commands/split.py
                                                                            def add_alias(self, alias: str) -> None:\n\"\"\"Add alias.\"\"\"\n    if alias not in self.aliases:\n        self.aliases.append(alias)\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.get_aliases","title":"get_aliases(self)","text":"

                                                                            Get the list of aliases.

                                                                            Source code in trestle/core/commands/split.py
                                                                            def get_aliases(self) -> List[str]:\n\"\"\"Get the list of aliases.\"\"\"\n    return self.aliases\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.mark_written","title":"mark_written(self)","text":"

                                                                            Mark this model as written.

                                                                            Source code in trestle/core/commands/split.py
                                                                            def mark_written(self) -> None:\n\"\"\"Mark this model as written.\"\"\"\n    self.written = True\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.AliasTracker.needs_writing","title":"needs_writing(self)","text":"

                                                                            Need to write the model.

                                                                            Source code in trestle/core/commands/split.py
                                                                            def needs_writing(self) -> bool:\n\"\"\"Need to write the model.\"\"\"\n    return not self.written\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd","title":" SplitCmd (CommandPlusDocs) ","text":"

                                                                            Split subcomponents on a trestle model.

                                                                            Source code in trestle/core/commands/split.py
                                                                            class SplitCmd(CommandPlusDocs):\n\"\"\"Split subcomponents on a trestle model.\"\"\"\n\n    name = 'split'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            f'-{const.ARG_FILE_SHORT}', f'--{const.ARG_FILE}', help=const.ARG_DESC_FILE + ' to split.', required=False\n        )\n        self.add_argument(\n            f'-{const.ARG_ELEMENT_SHORT}',\n            f'--{const.ARG_ELEMENT}',\n            help=const.ARG_DESC_ELEMENT + ' to split.',\n            required=False\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n\"\"\"Split an OSCAL file into elements.\"\"\"\n        try:\n            log.set_log_level_from_args(args)\n            trace.log('Entering trestle split.')\n            # get the Model\n            args_raw: Dict[str, str] = args.__dict__\n\n            # remove any quotes passed in as on windows platforms\n            elements_clean: str = args_raw[const.ARG_ELEMENT].strip(\"'\")\n\n            file_name = ''\n            file_name = '' if not args_raw[const.ARG_FILE] else args_raw[const.ARG_FILE]\n            # cwd must be in the model directory if file to split is not specified\n            effective_cwd = pathlib.Path.cwd()\n\n            return self.perform_split(effective_cwd, file_name, elements_clean, args.trestle_root)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while performing a split operation')\n\n    @classmethod\n    def perform_split(\n        cls, effective_cwd: pathlib.Path, file_name: str, elements: str, trestle_root: pathlib.Path\n    ) -> int:\n\"\"\"Perform the split operation.\n\n        Args:\n            effective_cwd: effective directory in which the the split operation is performed\n            file_name: file name of model to split, or '' if deduced from elements and cwd\n            elements: comma separated list of paths to strip from the file, with quotes removed\n\n        Returns:\n            0 on success and 1 on failure\n        \"\"\"\n        file_path_list: List[Tuple[str, str]] = []\n\n        if file_name:\n            file_path_list.append((file_name, elements))\n        else:\n            # cwd must be in the model directory if file to split is not specified\n            # find top directory for this model based on trestle root and cwd\n            model_dir = file_utils.extract_project_model_path(effective_cwd)\n            if model_dir is None:\n                raise TrestleError('Current directory must be within a model directory if file is not specified')\n\n            content_type: FileContentType = FileContentType.dir_to_content_type(model_dir)\n\n            # determine the file needed for each split path\n            element_paths = elements.split(',')\n            for path in element_paths:\n                element_path = ElementPath(path)\n                # if element path is relative use directory context to determine absolute path\n                element_path.make_absolute(model_dir, effective_cwd)\n                file_path = element_path.find_last_file_in_path(content_type, model_dir)\n                # now make the element path relative to the model file to be loaded\n                if file_path is None or element_path.make_relative(file_path.relative_to(model_dir)) != 0:\n                    raise TrestleError(f'Unable to match element path with files in model directory {element_path}')\n\n                file_path_list.append((file_path, element_path.to_string()))\n\n        # match paths to corresponding files since several paths may be split from the same file\n        file_path_dict: Dict[str, str] = {}\n        for file_path in file_path_list:\n            key = file_path[0]  # type: ignore\n            path = file_path[1]  # type: ignore\n            if key not in file_path_dict:\n                file_path_dict[key] = path\n            else:\n                current_path = file_path_dict[key]\n                file_path_dict[key] = f'{current_path},{path}'\n\n        for raw_file_name, element_path in file_path_dict.items():\n            file_path = file_utils.relative_resolve(pathlib.Path(raw_file_name), effective_cwd)\n            # this makes assumptions that the path is relative.\n            if not file_path.exists():\n                raise TrestleError(f'File {file_path} does not exist.')\n\n            content_type = FileContentType.to_content_type(file_path.suffix)\n\n            # find the base directory of the file\n            base_dir = file_path.parent\n            model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n\n            model: OscalBaseModel = model_type.oscal_read(file_path)\n\n            if cmd_utils.split_is_too_fine(element_path, model):\n                raise TrestleError('Cannot split the model to the level of uuids, strings, etc.')\n\n            # use the model itself to resolve any wildcards and create list of element paths\n            logger.debug(f'split calling parse_element_args on {element_path}')\n            # use contextual mode to parse\n\n            element_paths: List[ElementPath] = cmd_utils.parse_element_args(\n                model, element_path.split(','), base_dir.relative_to(trestle_root)\n            )\n\n            # analyze the split tree and determine which aliases should be stripped from each file\n            aliases_to_strip = cls.find_aliases_to_strip(element_paths)\n\n            # need the file name relative to the base directory\n            file_name_no_path = str(file_path.name)\n\n            split_plan = cls.split_model(\n                model, element_paths, base_dir, content_type, file_name_no_path, aliases_to_strip\n            )\n            trash.store(file_path, True)\n\n            try:\n                split_plan.execute()\n            except Exception as e:\n                trash.recover(file_path, True)\n                raise TrestleError(f'Split has failed with error: {e}.')\n\n        return CmdReturnCodes.SUCCESS.value\n\n    @classmethod\n    def prepare_sub_model_split_actions(\n        cls,\n        sub_model_item: OscalBaseModel,\n        sub_model_dir: pathlib.Path,\n        file_prefix: str,\n        content_type: FileContentType\n    ) -> List[Action]:\n\"\"\"Create split actions of sub model.\"\"\"\n        actions: List[Action] = []\n        file_name = cmd_utils.to_model_file_name(sub_model_item, file_prefix, content_type)\n        model_type = classname_to_alias(type(sub_model_item).__name__, AliasMode.JSON)\n        sub_model_file = sub_model_dir / file_name\n        actions.append(CreatePathAction(sub_model_file))\n        actions.append(WriteFileAction(sub_model_file, Element(sub_model_item, model_type), content_type))\n        return actions\n\n    @classmethod\n    def split_model_at_path_chain(\n        cls,\n        model_obj: OscalBaseModel,\n        element_paths: List[ElementPath],\n        base_dir: pathlib.Path,\n        content_type: FileContentType,\n        cur_path_index: int,\n        split_plan: Plan,\n        strip_root: bool,\n        root_file_name: str,\n        aliases_to_strip: Dict[str, AliasTracker],\n        last_one: bool = True\n    ) -> int:\n\"\"\"Recursively split the model at the provided chain of element paths.\n\n        It assumes that a chain of element paths starts at the cur_path_index with the first path ending\n        with a wildcard (*)\n\n        If the wildcard follows an element that is inherently a list of items, the list of items is extracted.\n        But if the wildcard follows a generic model than members of that model class found in the model will be\n        split off.  But only the non-trivial elements are removed, i.e. not str, int, datetime, etc.\n\n        Args:\n            model_obj: The OscalBaseModel to be split\n            element_paths: The List[ElementPath] of elements to split, including embedded wildcards\n            base_dir: pathlib.Path of the file being split\n            content_type: json or yaml files\n            cur_path_index: Index into the list of element paths for the current split operation\n            split_plan: The accumulated plan of actions needed to perform the split\n            strip_root: Whether to strip elements from the root object\n            root_file_name: Filename of root file that gets split into a list of items\n            aliases_to_strip: AliasTracker previously loaded with aliases that need to be split from each element\n            last_one: bool indicating last item in array has been split and stripped model can now be written\n\n        Returns:\n            int representing the index where the chain of the path ends.\n\n        Examples:\n            For example, element paths could have a list of paths as below for a `ComponentDefinition` model where\n            the first path is the start of the chain.\n\n            For each of the sub model described by the first element path (e.g component-defintion.components.*) in the\n            chain, the subsequent paths (e.g component.control-implementations.*) will be applied recursively\n            to retrieve the sub-sub models:\n            [\n                'component-definition.component.*',\n                'component.control-implementations.*'\n            ]\n            for a command like below:\n            trestle split -f component.yaml -e component-definition.components.*.control-implementations.*\n        \"\"\"\n        if split_plan is None:\n            raise TrestleError('Split plan must have been initialized')\n\n        if cur_path_index < 0:\n            raise TrestleError('Current index of the chain of paths cannot be less than 0')\n\n        # if there are no more element_paths, return the current plan\n        if cur_path_index >= len(element_paths):\n            return cur_path_index\n\n        # initialize local variables\n        element = Element(model_obj)\n        stripped_field_alias: List[str] = []\n\n        # get the sub_model specified by the element_path of this round\n        element_path = element_paths[cur_path_index]\n\n        # does the next element_path point back at me\n        is_parent = cur_path_index + 1 < len(element_paths) and element_paths[cur_path_index\n                                                                              + 1].get_parent() == element_path\n\n        # root dir name for sub models dir\n        # 00000__group.json will have the root_dir name as 00000__group for sub models of group\n        # catalog.json will have the root_dir name as catalog\n        root_dir = ''\n        if root_file_name != '':\n            root_dir = str(pathlib.Path(root_file_name).with_suffix(''))\n\n        sub_models = element.get_at(element_path, False)  # we call sub_models as in plural, but it can be just one\n\n        # assume cur_path_index is the end of the chain\n        # value of this variable may change during recursive split of the sub-models below\n        path_chain_end = cur_path_index\n\n        # if wildcard is present in the element_path and the next path in the chain has current path as the parent,\n        # Then deal with case of list, or split of arbitrary oscalbasemodel\n        if is_parent and element_path.get_last() is not ElementPath.WILDCARD:\n            # create dir for all sub model items\n            sub_models_dir = base_dir / element_path.to_root_path()\n            sub_model_plan = Plan()\n            path_chain_end = cls.split_model_at_path_chain(\n                sub_models,\n                element_paths,\n                sub_models_dir,\n                content_type,\n                cur_path_index + 1,\n                sub_model_plan,\n                True,\n                '',\n                aliases_to_strip\n            )\n            sub_model_actions = sub_model_plan.get_actions()\n            split_plan.add_actions(sub_model_actions)\n        elif element_path.get_last() == ElementPath.WILDCARD:\n            # extract sub-models into a dict with appropriate prefix\n            sub_model_items: Dict[str, OscalBaseModel] = {}\n            sub_models_dir = base_dir / element_path.to_file_path(root_dir=root_dir)\n            if isinstance(sub_models, list):\n                for i, sub_model_item in enumerate(sub_models):\n                    # e.g. `groups/00000_groups/`\n                    prefix = str(i).zfill(const.FILE_DIGIT_PREFIX_LENGTH)\n                    sub_model_items[prefix] = sub_model_item\n\n            # process list sub model items\n            count = 0\n            for key, sub_model_item in sub_model_items.items():\n                count += 1\n                # recursively split the sub-model if there are more element paths to traverse\n                # e.g. split component.control-implementations.*\n                require_recursive_split = cur_path_index + 1 < len(element_paths) and element_paths[\n                    cur_path_index + 1].get_parent() == element_path\n\n                if require_recursive_split:\n                    # prepare individual directory for each sub-model\n                    sub_root_file_name = cmd_utils.to_model_file_name(sub_model_item, key, content_type)\n                    sub_model_plan = Plan()\n\n                    last_one: bool = count == len(sub_model_items)\n                    path_chain_end = cls.split_model_at_path_chain(\n                        sub_model_item,\n                        element_paths,\n                        sub_models_dir,\n                        content_type,\n                        cur_path_index + 1,\n                        sub_model_plan,\n                        True,\n                        sub_root_file_name,\n                        aliases_to_strip,\n                        last_one\n                    )\n                    sub_model_actions = sub_model_plan.get_actions()\n                else:\n                    sub_model_actions = cls.prepare_sub_model_split_actions(\n                        sub_model_item, sub_models_dir, key, content_type\n                    )\n\n                split_plan.add_actions(sub_model_actions)\n        else:\n            # the chain of path ends at the current index.\n            # so no recursive call. Let's just write the sub model to the file and get out\n            if sub_models is not None:\n                sub_model_file = base_dir / element_path.to_file_path(content_type, root_dir=root_dir)\n                split_plan.add_action(CreatePathAction(sub_model_file))\n                split_plan.add_action(\n                    WriteFileAction(sub_model_file, Element(sub_models, element_path.get_element_name()), content_type)\n                )\n\n        # Strip the root model and add a WriteAction for the updated model object in the plan\n        if strip_root:\n            full_path = element_path.get_full()\n            path = '.'.join(full_path.split('.')[:-1])\n            aliases = [element_path.get_element_name()]\n            need_to_write = True\n            use_alias_dict = aliases_to_strip is not None and path in aliases_to_strip\n            if use_alias_dict:\n                aliases = aliases_to_strip[path].get_aliases()\n                need_to_write = aliases_to_strip[path].needs_writing()\n\n            stripped_model = model_obj.stripped_instance(stripped_fields_aliases=aliases)\n            # can mark it written even if it doesn't need writing since it is empty\n            # but if an array only mark it written if it's the last one\n            if last_one and use_alias_dict:\n                aliases_to_strip[path].mark_written()\n            # If it's an empty model after stripping the fields, don't create path and don't write\n            field_list = [x for x in model_obj.__fields__.keys() if model_obj.__fields__[x] is not None]\n            if set(field_list) == set(stripped_field_alias):\n                return path_chain_end\n\n            if need_to_write:\n                if root_file_name != '':\n                    root_file = base_dir / root_file_name\n                else:\n                    root_file = base_dir / element_path.to_root_path(content_type)\n\n                split_plan.add_action(CreatePathAction(root_file))\n                wrapper_alias = classname_to_alias(stripped_model.__class__.__name__, AliasMode.JSON)\n                split_plan.add_action(WriteFileAction(root_file, Element(stripped_model, wrapper_alias), content_type))\n\n        # return the end of the current path chain\n        return path_chain_end\n\n    @classmethod\n    def split_model(\n        cls,\n        model_obj: OscalBaseModel,\n        element_paths: List[ElementPath],\n        base_dir: pathlib.Path,\n        content_type: FileContentType,\n        root_file_name: str,\n        aliases_to_strip: Dict[str, AliasTracker]\n    ) -> Plan:\n\"\"\"Split the model at the provided element paths.\n\n        It returns a plan for the operation\n        \"\"\"\n        # initialize plan\n        split_plan = Plan()\n\n        # loop through the element path list and update the split_plan\n        stripped_field_alias = []\n        cur_path_index = 0\n        while cur_path_index < len(element_paths):\n            # extract the sub element name for each of the root path of the path chain\n            element_path = element_paths[cur_path_index]\n\n            if element_path.get_parent() is None and len(element_path.get()) > 1:\n                stripped_part = element_path.get()[1]\n                if stripped_part == ElementPath.WILDCARD:\n                    stripped_field_alias.append('__root__')\n                else:\n                    if stripped_part not in stripped_field_alias:\n                        stripped_field_alias.append(stripped_part)\n\n            # split model at the path chain\n            cur_path_index = cls.split_model_at_path_chain(\n                model_obj,\n                element_paths,\n                base_dir,\n                content_type,\n                cur_path_index,\n                split_plan,\n                False,\n                root_file_name,\n                aliases_to_strip\n            )\n\n            cur_path_index += 1\n\n        # strip the root model object and add a WriteAction\n        stripped_root = model_obj.stripped_instance(stripped_fields_aliases=stripped_field_alias)\n        # If it's an empty model after stripping the fields, don't create path and don't write\n        if set(model_obj.__fields__.keys()) == set(stripped_field_alias):\n            return split_plan\n        if root_file_name != '':\n            root_file = base_dir / root_file_name\n        else:\n            root_file = base_dir / element_paths[0].to_root_path(content_type)\n        split_plan.add_action(CreatePathAction(root_file, True))\n        wrapper_alias = classname_to_alias(stripped_root.__class__.__name__, AliasMode.JSON)\n        split_plan.add_action(WriteFileAction(root_file, Element(stripped_root, wrapper_alias), content_type))\n\n        return split_plan\n\n    @classmethod\n    def find_aliases_to_strip(cls, element_paths: List[ElementPath]) -> Dict[str, AliasTracker]:\n\"\"\"Find list of aliases that need to be stripped as each element written out.\"\"\"\n        # A given path may be present in several split actions\n        # Need to determine all parts stripped at each node in order to strip them all and\n        # write the stripped model only once\n        tracker_map: Dict[str, AliasTracker] = {}\n        for element_path in element_paths:\n            path = element_path.get_full()\n            path_parts = path.split('.')\n            alias = path_parts[-1]\n            if len(path_parts) > 2 and alias != '*':\n                root_path = '.'.join(path_parts[:-1])\n                if root_path in tracker_map:\n                    tracker_map[root_path].add_alias(alias)\n                else:\n                    tracker_map[root_path] = AliasTracker(aliases=[alias])\n        return tracker_map\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.find_aliases_to_strip","title":"find_aliases_to_strip(element_paths) classmethod","text":"

                                                                            Find list of aliases that need to be stripped as each element written out.

                                                                            Source code in trestle/core/commands/split.py
                                                                            @classmethod\ndef find_aliases_to_strip(cls, element_paths: List[ElementPath]) -> Dict[str, AliasTracker]:\n\"\"\"Find list of aliases that need to be stripped as each element written out.\"\"\"\n    # A given path may be present in several split actions\n    # Need to determine all parts stripped at each node in order to strip them all and\n    # write the stripped model only once\n    tracker_map: Dict[str, AliasTracker] = {}\n    for element_path in element_paths:\n        path = element_path.get_full()\n        path_parts = path.split('.')\n        alias = path_parts[-1]\n        if len(path_parts) > 2 and alias != '*':\n            root_path = '.'.join(path_parts[:-1])\n            if root_path in tracker_map:\n                tracker_map[root_path].add_alias(alias)\n            else:\n                tracker_map[root_path] = AliasTracker(aliases=[alias])\n    return tracker_map\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.perform_split","title":"perform_split(effective_cwd, file_name, elements, trestle_root) classmethod","text":"

                                                                            Perform the split operation.

                                                                            Parameters:

                                                                            Name Type Description Default effective_cwd Path

                                                                            effective directory in which the the split operation is performed

                                                                            required file_name str

                                                                            file name of model to split, or '' if deduced from elements and cwd

                                                                            required elements str

                                                                            comma separated list of paths to strip from the file, with quotes removed

                                                                            required

                                                                            Returns:

                                                                            Type Description int

                                                                            0 on success and 1 on failure

                                                                            Source code in trestle/core/commands/split.py
                                                                            @classmethod\ndef perform_split(\n    cls, effective_cwd: pathlib.Path, file_name: str, elements: str, trestle_root: pathlib.Path\n) -> int:\n\"\"\"Perform the split operation.\n\n    Args:\n        effective_cwd: effective directory in which the the split operation is performed\n        file_name: file name of model to split, or '' if deduced from elements and cwd\n        elements: comma separated list of paths to strip from the file, with quotes removed\n\n    Returns:\n        0 on success and 1 on failure\n    \"\"\"\n    file_path_list: List[Tuple[str, str]] = []\n\n    if file_name:\n        file_path_list.append((file_name, elements))\n    else:\n        # cwd must be in the model directory if file to split is not specified\n        # find top directory for this model based on trestle root and cwd\n        model_dir = file_utils.extract_project_model_path(effective_cwd)\n        if model_dir is None:\n            raise TrestleError('Current directory must be within a model directory if file is not specified')\n\n        content_type: FileContentType = FileContentType.dir_to_content_type(model_dir)\n\n        # determine the file needed for each split path\n        element_paths = elements.split(',')\n        for path in element_paths:\n            element_path = ElementPath(path)\n            # if element path is relative use directory context to determine absolute path\n            element_path.make_absolute(model_dir, effective_cwd)\n            file_path = element_path.find_last_file_in_path(content_type, model_dir)\n            # now make the element path relative to the model file to be loaded\n            if file_path is None or element_path.make_relative(file_path.relative_to(model_dir)) != 0:\n                raise TrestleError(f'Unable to match element path with files in model directory {element_path}')\n\n            file_path_list.append((file_path, element_path.to_string()))\n\n    # match paths to corresponding files since several paths may be split from the same file\n    file_path_dict: Dict[str, str] = {}\n    for file_path in file_path_list:\n        key = file_path[0]  # type: ignore\n        path = file_path[1]  # type: ignore\n        if key not in file_path_dict:\n            file_path_dict[key] = path\n        else:\n            current_path = file_path_dict[key]\n            file_path_dict[key] = f'{current_path},{path}'\n\n    for raw_file_name, element_path in file_path_dict.items():\n        file_path = file_utils.relative_resolve(pathlib.Path(raw_file_name), effective_cwd)\n        # this makes assumptions that the path is relative.\n        if not file_path.exists():\n            raise TrestleError(f'File {file_path} does not exist.')\n\n        content_type = FileContentType.to_content_type(file_path.suffix)\n\n        # find the base directory of the file\n        base_dir = file_path.parent\n        model_type, _ = ModelUtils.get_stripped_model_type(file_path, trestle_root)\n\n        model: OscalBaseModel = model_type.oscal_read(file_path)\n\n        if cmd_utils.split_is_too_fine(element_path, model):\n            raise TrestleError('Cannot split the model to the level of uuids, strings, etc.')\n\n        # use the model itself to resolve any wildcards and create list of element paths\n        logger.debug(f'split calling parse_element_args on {element_path}')\n        # use contextual mode to parse\n\n        element_paths: List[ElementPath] = cmd_utils.parse_element_args(\n            model, element_path.split(','), base_dir.relative_to(trestle_root)\n        )\n\n        # analyze the split tree and determine which aliases should be stripped from each file\n        aliases_to_strip = cls.find_aliases_to_strip(element_paths)\n\n        # need the file name relative to the base directory\n        file_name_no_path = str(file_path.name)\n\n        split_plan = cls.split_model(\n            model, element_paths, base_dir, content_type, file_name_no_path, aliases_to_strip\n        )\n        trash.store(file_path, True)\n\n        try:\n            split_plan.execute()\n        except Exception as e:\n            trash.recover(file_path, True)\n            raise TrestleError(f'Split has failed with error: {e}.')\n\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.prepare_sub_model_split_actions","title":"prepare_sub_model_split_actions(sub_model_item, sub_model_dir, file_prefix, content_type) classmethod","text":"

                                                                            Create split actions of sub model.

                                                                            Source code in trestle/core/commands/split.py
                                                                            @classmethod\ndef prepare_sub_model_split_actions(\n    cls,\n    sub_model_item: OscalBaseModel,\n    sub_model_dir: pathlib.Path,\n    file_prefix: str,\n    content_type: FileContentType\n) -> List[Action]:\n\"\"\"Create split actions of sub model.\"\"\"\n    actions: List[Action] = []\n    file_name = cmd_utils.to_model_file_name(sub_model_item, file_prefix, content_type)\n    model_type = classname_to_alias(type(sub_model_item).__name__, AliasMode.JSON)\n    sub_model_file = sub_model_dir / file_name\n    actions.append(CreatePathAction(sub_model_file))\n    actions.append(WriteFileAction(sub_model_file, Element(sub_model_item, model_type), content_type))\n    return actions\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.split_model","title":"split_model(model_obj, element_paths, base_dir, content_type, root_file_name, aliases_to_strip) classmethod","text":"

                                                                            Split the model at the provided element paths.

                                                                            It returns a plan for the operation

                                                                            Source code in trestle/core/commands/split.py
                                                                            @classmethod\ndef split_model(\n    cls,\n    model_obj: OscalBaseModel,\n    element_paths: List[ElementPath],\n    base_dir: pathlib.Path,\n    content_type: FileContentType,\n    root_file_name: str,\n    aliases_to_strip: Dict[str, AliasTracker]\n) -> Plan:\n\"\"\"Split the model at the provided element paths.\n\n    It returns a plan for the operation\n    \"\"\"\n    # initialize plan\n    split_plan = Plan()\n\n    # loop through the element path list and update the split_plan\n    stripped_field_alias = []\n    cur_path_index = 0\n    while cur_path_index < len(element_paths):\n        # extract the sub element name for each of the root path of the path chain\n        element_path = element_paths[cur_path_index]\n\n        if element_path.get_parent() is None and len(element_path.get()) > 1:\n            stripped_part = element_path.get()[1]\n            if stripped_part == ElementPath.WILDCARD:\n                stripped_field_alias.append('__root__')\n            else:\n                if stripped_part not in stripped_field_alias:\n                    stripped_field_alias.append(stripped_part)\n\n        # split model at the path chain\n        cur_path_index = cls.split_model_at_path_chain(\n            model_obj,\n            element_paths,\n            base_dir,\n            content_type,\n            cur_path_index,\n            split_plan,\n            False,\n            root_file_name,\n            aliases_to_strip\n        )\n\n        cur_path_index += 1\n\n    # strip the root model object and add a WriteAction\n    stripped_root = model_obj.stripped_instance(stripped_fields_aliases=stripped_field_alias)\n    # If it's an empty model after stripping the fields, don't create path and don't write\n    if set(model_obj.__fields__.keys()) == set(stripped_field_alias):\n        return split_plan\n    if root_file_name != '':\n        root_file = base_dir / root_file_name\n    else:\n        root_file = base_dir / element_paths[0].to_root_path(content_type)\n    split_plan.add_action(CreatePathAction(root_file, True))\n    wrapper_alias = classname_to_alias(stripped_root.__class__.__name__, AliasMode.JSON)\n    split_plan.add_action(WriteFileAction(root_file, Element(stripped_root, wrapper_alias), content_type))\n\n    return split_plan\n
                                                                            "},{"location":"api_reference/trestle.core.commands.split/#trestle.core.commands.split.SplitCmd.split_model_at_path_chain","title":"split_model_at_path_chain(model_obj, element_paths, base_dir, content_type, cur_path_index, split_plan, strip_root, root_file_name, aliases_to_strip, last_one=True) classmethod","text":"

                                                                            Recursively split the model at the provided chain of element paths.

                                                                            It assumes that a chain of element paths starts at the cur_path_index with the first path ending with a wildcard (*)

                                                                            If the wildcard follows an element that is inherently a list of items, the list of items is extracted. But if the wildcard follows a generic model than members of that model class found in the model will be split off. But only the non-trivial elements are removed, i.e. not str, int, datetime, etc.

                                                                            Parameters:

                                                                            Name Type Description Default model_obj OscalBaseModel

                                                                            The OscalBaseModel to be split

                                                                            required element_paths List[trestle.core.models.elements.ElementPath]

                                                                            The List[ElementPath] of elements to split, including embedded wildcards

                                                                            required base_dir Path

                                                                            pathlib.Path of the file being split

                                                                            required content_type FileContentType

                                                                            json or yaml files

                                                                            required cur_path_index int

                                                                            Index into the list of element paths for the current split operation

                                                                            required split_plan Plan

                                                                            The accumulated plan of actions needed to perform the split

                                                                            required strip_root bool

                                                                            Whether to strip elements from the root object

                                                                            required root_file_name str

                                                                            Filename of root file that gets split into a list of items

                                                                            required aliases_to_strip Dict[str, trestle.core.commands.split.AliasTracker]

                                                                            AliasTracker previously loaded with aliases that need to be split from each element

                                                                            required last_one bool

                                                                            bool indicating last item in array has been split and stripped model can now be written

                                                                            True

                                                                            Returns:

                                                                            Type Description int

                                                                            int representing the index where the chain of the path ends.

                                                                            Examples:

                                                                            For example, element paths could have a list of paths as below for a ComponentDefinition model where the first path is the start of the chain.

                                                                            For each of the sub model described by the first element path (e.g component-defintion.components.) in the chain, the subsequent paths (e.g component.control-implementations.) will be applied recursively to retrieve the sub-sub models: [ 'component-definition.component.', 'component.control-implementations.' ] for a command like below: trestle split -f component.yaml -e component-definition.components..control-implementations.

                                                                            Source code in trestle/core/commands/split.py
                                                                            @classmethod\ndef split_model_at_path_chain(\n    cls,\n    model_obj: OscalBaseModel,\n    element_paths: List[ElementPath],\n    base_dir: pathlib.Path,\n    content_type: FileContentType,\n    cur_path_index: int,\n    split_plan: Plan,\n    strip_root: bool,\n    root_file_name: str,\n    aliases_to_strip: Dict[str, AliasTracker],\n    last_one: bool = True\n) -> int:\n\"\"\"Recursively split the model at the provided chain of element paths.\n\n    It assumes that a chain of element paths starts at the cur_path_index with the first path ending\n    with a wildcard (*)\n\n    If the wildcard follows an element that is inherently a list of items, the list of items is extracted.\n    But if the wildcard follows a generic model than members of that model class found in the model will be\n    split off.  But only the non-trivial elements are removed, i.e. not str, int, datetime, etc.\n\n    Args:\n        model_obj: The OscalBaseModel to be split\n        element_paths: The List[ElementPath] of elements to split, including embedded wildcards\n        base_dir: pathlib.Path of the file being split\n        content_type: json or yaml files\n        cur_path_index: Index into the list of element paths for the current split operation\n        split_plan: The accumulated plan of actions needed to perform the split\n        strip_root: Whether to strip elements from the root object\n        root_file_name: Filename of root file that gets split into a list of items\n        aliases_to_strip: AliasTracker previously loaded with aliases that need to be split from each element\n        last_one: bool indicating last item in array has been split and stripped model can now be written\n\n    Returns:\n        int representing the index where the chain of the path ends.\n\n    Examples:\n        For example, element paths could have a list of paths as below for a `ComponentDefinition` model where\n        the first path is the start of the chain.\n\n        For each of the sub model described by the first element path (e.g component-defintion.components.*) in the\n        chain, the subsequent paths (e.g component.control-implementations.*) will be applied recursively\n        to retrieve the sub-sub models:\n        [\n            'component-definition.component.*',\n            'component.control-implementations.*'\n        ]\n        for a command like below:\n        trestle split -f component.yaml -e component-definition.components.*.control-implementations.*\n    \"\"\"\n    if split_plan is None:\n        raise TrestleError('Split plan must have been initialized')\n\n    if cur_path_index < 0:\n        raise TrestleError('Current index of the chain of paths cannot be less than 0')\n\n    # if there are no more element_paths, return the current plan\n    if cur_path_index >= len(element_paths):\n        return cur_path_index\n\n    # initialize local variables\n    element = Element(model_obj)\n    stripped_field_alias: List[str] = []\n\n    # get the sub_model specified by the element_path of this round\n    element_path = element_paths[cur_path_index]\n\n    # does the next element_path point back at me\n    is_parent = cur_path_index + 1 < len(element_paths) and element_paths[cur_path_index\n                                                                          + 1].get_parent() == element_path\n\n    # root dir name for sub models dir\n    # 00000__group.json will have the root_dir name as 00000__group for sub models of group\n    # catalog.json will have the root_dir name as catalog\n    root_dir = ''\n    if root_file_name != '':\n        root_dir = str(pathlib.Path(root_file_name).with_suffix(''))\n\n    sub_models = element.get_at(element_path, False)  # we call sub_models as in plural, but it can be just one\n\n    # assume cur_path_index is the end of the chain\n    # value of this variable may change during recursive split of the sub-models below\n    path_chain_end = cur_path_index\n\n    # if wildcard is present in the element_path and the next path in the chain has current path as the parent,\n    # Then deal with case of list, or split of arbitrary oscalbasemodel\n    if is_parent and element_path.get_last() is not ElementPath.WILDCARD:\n        # create dir for all sub model items\n        sub_models_dir = base_dir / element_path.to_root_path()\n        sub_model_plan = Plan()\n        path_chain_end = cls.split_model_at_path_chain(\n            sub_models,\n            element_paths,\n            sub_models_dir,\n            content_type,\n            cur_path_index + 1,\n            sub_model_plan,\n            True,\n            '',\n            aliases_to_strip\n        )\n        sub_model_actions = sub_model_plan.get_actions()\n        split_plan.add_actions(sub_model_actions)\n    elif element_path.get_last() == ElementPath.WILDCARD:\n        # extract sub-models into a dict with appropriate prefix\n        sub_model_items: Dict[str, OscalBaseModel] = {}\n        sub_models_dir = base_dir / element_path.to_file_path(root_dir=root_dir)\n        if isinstance(sub_models, list):\n            for i, sub_model_item in enumerate(sub_models):\n                # e.g. `groups/00000_groups/`\n                prefix = str(i).zfill(const.FILE_DIGIT_PREFIX_LENGTH)\n                sub_model_items[prefix] = sub_model_item\n\n        # process list sub model items\n        count = 0\n        for key, sub_model_item in sub_model_items.items():\n            count += 1\n            # recursively split the sub-model if there are more element paths to traverse\n            # e.g. split component.control-implementations.*\n            require_recursive_split = cur_path_index + 1 < len(element_paths) and element_paths[\n                cur_path_index + 1].get_parent() == element_path\n\n            if require_recursive_split:\n                # prepare individual directory for each sub-model\n                sub_root_file_name = cmd_utils.to_model_file_name(sub_model_item, key, content_type)\n                sub_model_plan = Plan()\n\n                last_one: bool = count == len(sub_model_items)\n                path_chain_end = cls.split_model_at_path_chain(\n                    sub_model_item,\n                    element_paths,\n                    sub_models_dir,\n                    content_type,\n                    cur_path_index + 1,\n                    sub_model_plan,\n                    True,\n                    sub_root_file_name,\n                    aliases_to_strip,\n                    last_one\n                )\n                sub_model_actions = sub_model_plan.get_actions()\n            else:\n                sub_model_actions = cls.prepare_sub_model_split_actions(\n                    sub_model_item, sub_models_dir, key, content_type\n                )\n\n            split_plan.add_actions(sub_model_actions)\n    else:\n        # the chain of path ends at the current index.\n        # so no recursive call. Let's just write the sub model to the file and get out\n        if sub_models is not None:\n            sub_model_file = base_dir / element_path.to_file_path(content_type, root_dir=root_dir)\n            split_plan.add_action(CreatePathAction(sub_model_file))\n            split_plan.add_action(\n                WriteFileAction(sub_model_file, Element(sub_models, element_path.get_element_name()), content_type)\n            )\n\n    # Strip the root model and add a WriteAction for the updated model object in the plan\n    if strip_root:\n        full_path = element_path.get_full()\n        path = '.'.join(full_path.split('.')[:-1])\n        aliases = [element_path.get_element_name()]\n        need_to_write = True\n        use_alias_dict = aliases_to_strip is not None and path in aliases_to_strip\n        if use_alias_dict:\n            aliases = aliases_to_strip[path].get_aliases()\n            need_to_write = aliases_to_strip[path].needs_writing()\n\n        stripped_model = model_obj.stripped_instance(stripped_fields_aliases=aliases)\n        # can mark it written even if it doesn't need writing since it is empty\n        # but if an array only mark it written if it's the last one\n        if last_one and use_alias_dict:\n            aliases_to_strip[path].mark_written()\n        # If it's an empty model after stripping the fields, don't create path and don't write\n        field_list = [x for x in model_obj.__fields__.keys() if model_obj.__fields__[x] is not None]\n        if set(field_list) == set(stripped_field_alias):\n            return path_chain_end\n\n        if need_to_write:\n            if root_file_name != '':\n                root_file = base_dir / root_file_name\n            else:\n                root_file = base_dir / element_path.to_root_path(content_type)\n\n            split_plan.add_action(CreatePathAction(root_file))\n            wrapper_alias = classname_to_alias(stripped_model.__class__.__name__, AliasMode.JSON)\n            split_plan.add_action(WriteFileAction(root_file, Element(stripped_model, wrapper_alias), content_type))\n\n    # return the end of the current path chain\n    return path_chain_end\n
                                                                            "},{"location":"api_reference/trestle.core.commands.task/","title":"task","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task","title":"trestle.core.commands.task","text":"

                                                                            Trestle task command.

                                                                            "},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task.TaskCmd","title":" TaskCmd (CommandPlusDocs) ","text":"

                                                                            Run arbitrary trestle tasks in a simple and extensible methodology.

                                                                            Source code in trestle/core/commands/task.py
                                                                            class TaskCmd(CommandPlusDocs):\n\"\"\"Run arbitrary trestle tasks in a simple and extensible methodology.\"\"\"\n\n    name = 'task'\n\n    def _init_arguments(self) -> None:\n        self.add_argument(\n            'task',\n            nargs='?',\n            type=str,\n            help='The name of the task to be run, trestle task -l will list available tasks.'\n        )\n        self.add_argument('-l', '--list', action='store_true', help='List the available tasks')\n        self.add_argument(\n            '-c', '--config', type=pathlib.Path, help='Pass a customized configuration file specifically for a task'\n        )\n        self.add_argument('-i', '--info', action='store_true', help='Print information about a particular task.')\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            logger.debug('Entering trestle task.')\n            log.set_log_level_from_args(args)\n            # Initial logic for conflicting args\n            if args.task and args.list:\n                raise TrestleIncorrectArgsError('Task name or -l can be provided not both.')\n\n            if not args.task and not args.list:\n                raise TrestleIncorrectArgsError(\n                    'Either a trestle task or \"-l/--list\" shoudl be passed as input arguments.'\n                )\n\n            # Ensure trestle directory (must be true)\n            trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n            if not trestle_root or not file_utils.is_valid_project_root(args.trestle_root):\n                raise TrestleError(f'Given directory: {trestle_root} is not a trestle project.')\n\n            config_path = trestle_root / const.TRESTLE_CONFIG_DIR / const.TRESTLE_CONFIG_FILE\n\n            if args.config:\n                config_path = pathlib.Path(args.config)\n            if not config_path.exists():\n                raise TrestleError(f'Config file at {config_path} does not exist.')\n\n            # permit ${name} in config definitions\n            global_config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())\n            global_config.read_file(config_path.open('r', encoding=const.FILE_ENCODING))\n            # run setup\n            task_index = self._build_task_index()\n\n            # Clean to run\n            if args.list:\n                self._list_tasks(task_index)\n                return CmdReturnCodes.SUCCESS.value\n            # run the task\n            if args.task not in task_index.keys():\n                raise TrestleIncorrectArgsError(f'Unknown trestle task: {args.task}')\n\n            logger.debug(f'Loading task: {args.task}')\n            section_label = 'task.' + args.task\n            config_section: Optional[configparser.SectionProxy] = None\n            if section_label in global_config.sections():\n                config_section = global_config[section_label]\n            else:\n                logger.warning(\n                    f'Config file was not configured with the appropriate section for the task: \"[{section_label}]\"'\n                )\n\n            task = task_index[args.task](config_section)\n            if args.info:\n                task.print_info()\n                return CmdReturnCodes.SUCCESS.value\n\n            simulate_result = task.simulate()\n            if not (simulate_result == TaskOutcome.SIM_SUCCESS):\n                raise TrestleError(f'Task {args.task} reported a {simulate_result}')\n\n            actual_result = task.execute()\n            if not (actual_result == TaskOutcome.SUCCESS):\n                raise TrestleError(f'Task {args.task} reported a {actual_result}')\n\n            logger.info(f'Task: {args.task} executed successfully.')\n            return CmdReturnCodes.SUCCESS.value\n\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while executing Trestle task')\n\n    def _build_task_index(self) -> Dict[str, Type[TaskBase]]:\n\"\"\"Build an index of all classes in which are tasks and present as a dictionary.\"\"\"\n        task_index: Dict[str, Type[TaskBase]] = {}\n        pkgpath = str(pathlib.Path(trestle.tasks.__file__).parent)\n        for _, name, _ in pkgutil.iter_modules([pkgpath]):\n            __import__(f'trestle.tasks.{name}')\n            clsmembers = inspect.getmembers(sys.modules[f'trestle.tasks.{name}'], inspect.isclass)\n            for candidate in clsmembers:\n                if issubclass(candidate[1], TaskBase):\n                    task_index[candidate[1].name] = candidate[1]\n        return task_index\n\n    def _list_tasks(self, task_index: Dict[str, Type[TaskBase]]) -> None:\n        logger.info('Available tasks:')\n        for key in task_index.keys():\n            logger.info(f'    {key}')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.task/#trestle.core.commands.task.TaskCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.validate/","title":"validate","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate","title":"trestle.core.commands.validate","text":"

                                                                            Trestle Validate Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate.ValidateCmd","title":" ValidateCmd (CommandPlusDocs) ","text":"

                                                                            Validate contents of a trestle model in different modes.

                                                                            Source code in trestle/core/commands/validate.py
                                                                            class ValidateCmd(CommandPlusDocs):\n\"\"\"Validate contents of a trestle model in different modes.\"\"\"\n\n    name = ARG_VALIDATE\n\n    def _init_arguments(self) -> None:\n        vfact.init_arguments(self)\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            log.set_log_level_from_args(args)\n\n            mode_args = argparse.Namespace(mode=VAL_MODE_ALL)\n            validator = vfact.validator_factory.get(mode_args)\n\n            return validator.validate(args)\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error while validating contents of a trestle model')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.validate/#trestle.core.commands.validate.ValidateCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.commands.version/","title":"version","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version","title":"trestle.core.commands.version","text":"

                                                                            Trestle Validate Command.

                                                                            "},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version.VersionCmd","title":" VersionCmd (CommandBase) ","text":"

                                                                            Output version info for trestle and OSCAL.

                                                                            Source code in trestle/core/commands/version.py
                                                                            class VersionCmd(CommandBase):\n\"\"\"Output version info for trestle and OSCAL.\"\"\"\n\n    name = 'version'\n\n    def _init_arguments(self) -> None:\n        self.add_argument('-n', '--name', help='Name of the OSCAL model', default=None, type=str)\n        self.add_argument(\n            '-t',\n            '--type',\n            help='Type of the model being queried: (catalog, profile, component-definition, ...)',\n            default=None,\n            type=str\n        )\n\n    def _get_version(self, type_name: str, obj_name: str, trestle_root: pathlib.Path) -> str:\n\"\"\"Fetch the version of the OSCAL object from its metadata.\"\"\"\n        oscal_object, obj_path = ModelUtils.load_model_for_type(trestle_root, type_name, obj_name)  # type: ignore\n\n        if not (oscal_object.metadata or oscal_object.metadata.version):  # type: ignore\n            raise TrestleError(f'Unable to determine the version. Metadata version is missing in model: {obj_path}.')\n\n        return oscal_object.metadata.version\n\n    def _run(self, args: argparse.Namespace) -> int:\n        try:\n            status = CmdReturnCodes.COMMAND_ERROR.value\n\n            if not args.name and not args.type:\n                version_string = f'Trestle version v{__version__} based on OSCAL version {OSCAL_VERSION}'\n                self.out(version_string)\n                status = CmdReturnCodes.SUCCESS.value\n\n            if not (args.name and args.type) and (args.name or args.type):\n                raise TrestleError('Either both arguments --name and --type should be provided or none.')\n\n            if args.name and args.type:\n                trestle_root = pathlib.Path(args.trestle_root)\n                version = self._get_version(args.type, args.name, trestle_root)\n                version_string = f'Version of OSCAL object of {args.name} {args.type} is: {version}.'\n                self.out(version_string)\n                status = CmdReturnCodes.SUCCESS.value\n\n            return status\n        except Exception as e:  # pragma: no cover\n            return handle_generic_command_exception(e, logger, 'Error occurred when running trestle version')\n
                                                                            "},{"location":"api_reference/trestle.core.commands.version/#trestle.core.commands.version.VersionCmd.name","title":"name","text":""},{"location":"api_reference/trestle.core.control_context/","title":"control_context","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context","title":"trestle.core.control_context","text":"

                                                                            Provide a context for control operations.

                                                                            "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose","title":" ContextPurpose (Enum) ","text":"

                                                                            Specify the modality of the control markdown.

                                                                            Source code in trestle/core/control_context.py
                                                                            class ContextPurpose(Enum):\n\"\"\"Specify the modality of the control markdown.\"\"\"\n\n    CATALOG = 0\n    COMPONENT = 1\n    PROFILE = 2\n    SSP = 3\n
                                                                            "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.CATALOG","title":"CATALOG","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.COMPONENT","title":"COMPONENT","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.PROFILE","title":"PROFILE","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ContextPurpose.SSP","title":"SSP","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext","title":" ControlContext dataclass","text":"

                                                                            Class encapsulating control markdown usage.

                                                                            Source code in trestle/core/control_context.py
                                                                            @dataclass\nclass ControlContext:\n\"\"\"Class encapsulating control markdown usage.\"\"\"\n\n    purpose: ContextPurpose\n    to_markdown: bool\n    trestle_root: pathlib.Path\n    md_root: pathlib.Path\n    prompt_responses: bool\n    include_all_parts: bool\n    overwrite_header_values: bool\n    set_parameters_flag: bool\n    cli_yaml_header: Optional[Dict[Any, Any]] = None\n    sections_dict: Optional[Dict[str, str]] = None\n    profile: Optional[prof.Profile] = None\n    required_sections: Optional[List[str]] = None\n    allowed_sections: Optional[List[str]] = None\n    comp_def: Optional[comp.ComponentDefinition] = None\n    comp_name: Optional[str] = None\n    component: Optional[comp.DefinedComponent] = None\n    comp_def_name_list: Optional[List[str]] = None\n    inherited_props: Optional[Dict[str, Any]] = None\n    rules_dict: Optional[Dict[str, Dict[str, Any]]] = None\n    rules_params_dict: Optional[Dict[str, Dict[str, Any]]] = None\n    control_implementation: Optional[comp.ControlImplementation] = None\n    uri_name_map: Optional[Dict[str, str]] = None\n    comp_dict: Optional[CompDict] = None\n    merged_header: Optional[Dict[str, Any]] = None\n\n    @classmethod\n    def generate(\n        cls,\n        purpose: ContextPurpose,\n        to_markdown: bool,\n        trestle_root: pathlib.Path,\n        md_root: pathlib.Path,\n        prompt_responses: bool = False,\n        include_all_parts: bool = False,\n        overwrite_header_values: bool = False,\n        set_parameters_flag: bool = False,\n        cli_yaml_header: Optional[Dict[Any, Any]] = None,\n        sections_dict: Optional[Dict[str, str]] = None,\n        profile: Optional[prof.Profile] = None,\n        required_sections: Optional[List[str]] = None,\n        allowed_sections: Optional[List[str]] = None,\n        comp_def: Optional[comp.ComponentDefinition] = None,\n        comp_name: Optional[str] = None,\n        component: Optional[comp.DefinedComponent] = None,\n        comp_def_name_list: Optional[List[str]] = None,\n        inherited_props: Optional[Dict[str, Any]] = None,\n        rules_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n        rules_params_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n        control_implementation: Optional[comp.ControlImplementation] = None,\n        uri_name_map: Optional[Dict[str, str]] = None,\n        comp_dict: Optional[CompDict] = None,\n        merged_header: Optional[Dict[str, Any]] = None\n    ) -> ControlContext:\n\"\"\"Generate control context of the needed type.\"\"\"\n        context = cls(\n            purpose,\n            to_markdown,\n            trestle_root,\n            md_root,\n            prompt_responses,\n            include_all_parts,\n            overwrite_header_values,\n            set_parameters_flag,\n            cli_yaml_header=cli_yaml_header,\n            sections_dict=sections_dict,\n            profile=profile,\n            required_sections=required_sections,\n            allowed_sections=allowed_sections,\n            comp_def=comp_def,\n            comp_name=comp_name,\n            component=component,\n            comp_def_name_list=comp_def_name_list,\n            inherited_props=inherited_props,\n            rules_dict=rules_dict,\n            rules_params_dict=rules_params_dict,\n            control_implementation=control_implementation,\n            uri_name_map=uri_name_map,\n            comp_dict=comp_dict\n        )\n        context.cli_yaml_header = as_dict(cli_yaml_header)\n        context.sections_dict = as_dict(sections_dict)\n        context.merged_header = as_dict(merged_header)\n        # catalog generate always sets params\n        if to_markdown:\n            context.set_parameters = True\n        return context\n\n    @classmethod\n    def clone(cls, context: ControlContext) -> ControlContext:\n\"\"\"Create a deep clone of the context without duplicating large objects.\"\"\"\n        new_context = cls(\n            context.purpose,\n            context.to_markdown,\n            context.trestle_root,\n            context.md_root,\n            context.prompt_responses,\n            context.include_all_parts,\n            context.overwrite_header_values,\n            context.set_parameters_flag,\n            cli_yaml_header=copy.deepcopy(context.cli_yaml_header),\n            sections_dict=copy.deepcopy(context.sections_dict),\n            profile=context.profile,\n            required_sections=context.required_sections,\n            allowed_sections=context.allowed_sections,\n            comp_def=context.comp_def,\n            comp_name=context.comp_name,\n            component=context.component,\n            comp_def_name_list=context.comp_def_name_list,\n            inherited_props=copy.deepcopy(context.inherited_props),\n            rules_dict=copy.deepcopy(context.rules_dict),\n            rules_params_dict=copy.deepcopy(context.rules_params_dict),\n            control_implementation=copy.deepcopy(context.control_implementation),\n            uri_name_map=context.uri_name_map,\n            comp_dict=copy.deepcopy(context.comp_dict),\n            merged_header=copy.deepcopy(context.merged_header)\n        )\n        return new_context\n
                                                                            "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.allowed_sections","title":"allowed_sections: Optional[List[str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.cli_yaml_header","title":"cli_yaml_header: Optional[Dict[Any, Any]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_def","title":"comp_def: Optional[trestle.oscal.component.ComponentDefinition] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_def_name_list","title":"comp_def_name_list: Optional[List[str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_dict","title":"comp_dict: Optional[Dict[str, Dict[str, trestle.core.control_interface.ComponentImpInfo]]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.comp_name","title":"comp_name: Optional[str] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.component","title":"component: Optional[trestle.oscal.component.DefinedComponent] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.control_implementation","title":"control_implementation: Optional[trestle.oscal.component.ControlImplementation] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.include_all_parts","title":"include_all_parts: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.inherited_props","title":"inherited_props: Optional[Dict[str, Any]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.md_root","title":"md_root: Path dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.merged_header","title":"merged_header: Optional[Dict[str, Any]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.overwrite_header_values","title":"overwrite_header_values: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.profile","title":"profile: Optional[trestle.oscal.profile.Profile] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.prompt_responses","title":"prompt_responses: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.purpose","title":"purpose: ContextPurpose dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.required_sections","title":"required_sections: Optional[List[str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.rules_dict","title":"rules_dict: Optional[Dict[str, Dict[str, Any]]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.rules_params_dict","title":"rules_params_dict: Optional[Dict[str, Dict[str, Any]]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.sections_dict","title":"sections_dict: Optional[Dict[str, str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.set_parameters_flag","title":"set_parameters_flag: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.to_markdown","title":"to_markdown: bool dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.trestle_root","title":"trestle_root: Path dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.uri_name_map","title":"uri_name_map: Optional[Dict[str, str]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.__init__","title":"__init__(self, purpose, to_markdown, trestle_root, md_root, prompt_responses, include_all_parts, overwrite_header_values, set_parameters_flag, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) special","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.clone","title":"clone(context) classmethod","text":"

                                                                            Create a deep clone of the context without duplicating large objects.

                                                                            Source code in trestle/core/control_context.py
                                                                            @classmethod\ndef clone(cls, context: ControlContext) -> ControlContext:\n\"\"\"Create a deep clone of the context without duplicating large objects.\"\"\"\n    new_context = cls(\n        context.purpose,\n        context.to_markdown,\n        context.trestle_root,\n        context.md_root,\n        context.prompt_responses,\n        context.include_all_parts,\n        context.overwrite_header_values,\n        context.set_parameters_flag,\n        cli_yaml_header=copy.deepcopy(context.cli_yaml_header),\n        sections_dict=copy.deepcopy(context.sections_dict),\n        profile=context.profile,\n        required_sections=context.required_sections,\n        allowed_sections=context.allowed_sections,\n        comp_def=context.comp_def,\n        comp_name=context.comp_name,\n        component=context.component,\n        comp_def_name_list=context.comp_def_name_list,\n        inherited_props=copy.deepcopy(context.inherited_props),\n        rules_dict=copy.deepcopy(context.rules_dict),\n        rules_params_dict=copy.deepcopy(context.rules_params_dict),\n        control_implementation=copy.deepcopy(context.control_implementation),\n        uri_name_map=context.uri_name_map,\n        comp_dict=copy.deepcopy(context.comp_dict),\n        merged_header=copy.deepcopy(context.merged_header)\n    )\n    return new_context\n
                                                                            "},{"location":"api_reference/trestle.core.control_context/#trestle.core.control_context.ControlContext.generate","title":"generate(purpose, to_markdown, trestle_root, md_root, prompt_responses=False, include_all_parts=False, overwrite_header_values=False, set_parameters_flag=False, cli_yaml_header=None, sections_dict=None, profile=None, required_sections=None, allowed_sections=None, comp_def=None, comp_name=None, component=None, comp_def_name_list=None, inherited_props=None, rules_dict=None, rules_params_dict=None, control_implementation=None, uri_name_map=None, comp_dict=None, merged_header=None) classmethod","text":"

                                                                            Generate control context of the needed type.

                                                                            Source code in trestle/core/control_context.py
                                                                            @classmethod\ndef generate(\n    cls,\n    purpose: ContextPurpose,\n    to_markdown: bool,\n    trestle_root: pathlib.Path,\n    md_root: pathlib.Path,\n    prompt_responses: bool = False,\n    include_all_parts: bool = False,\n    overwrite_header_values: bool = False,\n    set_parameters_flag: bool = False,\n    cli_yaml_header: Optional[Dict[Any, Any]] = None,\n    sections_dict: Optional[Dict[str, str]] = None,\n    profile: Optional[prof.Profile] = None,\n    required_sections: Optional[List[str]] = None,\n    allowed_sections: Optional[List[str]] = None,\n    comp_def: Optional[comp.ComponentDefinition] = None,\n    comp_name: Optional[str] = None,\n    component: Optional[comp.DefinedComponent] = None,\n    comp_def_name_list: Optional[List[str]] = None,\n    inherited_props: Optional[Dict[str, Any]] = None,\n    rules_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n    rules_params_dict: Optional[Dict[str, Dict[str, Any]]] = None,\n    control_implementation: Optional[comp.ControlImplementation] = None,\n    uri_name_map: Optional[Dict[str, str]] = None,\n    comp_dict: Optional[CompDict] = None,\n    merged_header: Optional[Dict[str, Any]] = None\n) -> ControlContext:\n\"\"\"Generate control context of the needed type.\"\"\"\n    context = cls(\n        purpose,\n        to_markdown,\n        trestle_root,\n        md_root,\n        prompt_responses,\n        include_all_parts,\n        overwrite_header_values,\n        set_parameters_flag,\n        cli_yaml_header=cli_yaml_header,\n        sections_dict=sections_dict,\n        profile=profile,\n        required_sections=required_sections,\n        allowed_sections=allowed_sections,\n        comp_def=comp_def,\n        comp_name=comp_name,\n        component=component,\n        comp_def_name_list=comp_def_name_list,\n        inherited_props=inherited_props,\n        rules_dict=rules_dict,\n        rules_params_dict=rules_params_dict,\n        control_implementation=control_implementation,\n        uri_name_map=uri_name_map,\n        comp_dict=comp_dict\n    )\n    context.cli_yaml_header = as_dict(cli_yaml_header)\n    context.sections_dict = as_dict(sections_dict)\n    context.merged_header = as_dict(merged_header)\n    # catalog generate always sets params\n    if to_markdown:\n        context.set_parameters = True\n    return context\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/","title":"control_interface","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface","title":"trestle.core.control_interface","text":"

                                                                            Handle queries and utility operations on controls in memory.

                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.CompDict","title":"CompDict","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo","title":" ComponentImpInfo dataclass","text":"

                                                                            Class to capture component prose and status.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @dataclass\nclass ComponentImpInfo:\n\"\"\"Class to capture component prose and status.\"\"\"\n\n    prose: str\n    rules: List[str]\n    props: List[common.Property]\n    # the lambda is needed to prevent a mutable from being used as a default\n    # without the lambda it would break python 3.11 and is a bug either way\n    status: common.ImplementationStatus = field(\n        default_factory=lambda: common.ImplementationStatus(state=const.STATUS_OPERATIONAL)\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.props","title":"props: List[trestle.oscal.common.Property] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.prose","title":"prose: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.rules","title":"rules: List[str] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.status","title":"status: ImplementationStatus dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.__init__","title":"__init__(self, prose, rules, props, status=<factory>) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ComponentImpInfo.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface","title":" ControlInterface ","text":"

                                                                            Class to interact with controls in memory.

                                                                            Source code in trestle/core/control_interface.py
                                                                            class ControlInterface:\n\"\"\"Class to interact with controls in memory.\"\"\"\n\n    @staticmethod\n    def _wrap_label(label: str):\n        l_side = '\\['\n        r_side = '\\]'\n        wrapped = '' if label == '' else f'{l_side}{label}{r_side}'\n        return wrapped\n\n    @staticmethod\n    def _gap_join(a_str: str, b_str: str) -> str:\n        a_clean = a_str.strip()\n        b_clean = b_str.strip()\n        if not b_clean:\n            return a_clean\n        gap = '\\n\\n' if a_clean else ''\n        return a_clean + gap + b_clean\n\n    @staticmethod\n    def _get_control_section_part(part: common.Part, section_name: str) -> str:\n\"\"\"Get the prose for a named section in the control.\"\"\"\n        prose = ''\n        if part.name == section_name and part.prose is not None:\n            prose = ControlInterface._gap_join(prose, part.prose)\n        if part.parts:\n            for sub_part in part.parts:\n                prose = ControlInterface._gap_join(\n                    prose, ControlInterface._get_control_section_part(sub_part, section_name)\n                )\n        return prose\n\n    @staticmethod\n    def get_control_section_prose(control: cat.Control, section_name: str) -> str:\n\"\"\"Get the prose for the control section.\"\"\"\n        prose = ''\n        if control.parts:\n            for part in control.parts:\n                prose = ControlInterface._gap_join(\n                    prose, ControlInterface._get_control_section_part(part, section_name)\n                )\n        return prose\n\n    @staticmethod\n    def _find_section_info(part: common.Part, skip_section_list: List[str]) -> Tuple[str, str, str]:\n\"\"\"Find section not in list.\"\"\"\n        if part.prose and part.name not in skip_section_list:\n            return part.id, part.name, part.title\n        if part.parts:\n            for sub_part in part.parts:\n                id_, name, title = ControlInterface._find_section_info(sub_part, skip_section_list)\n                if id_:\n                    return id_, name, title\n        return '', '', ''\n\n    @staticmethod\n    def _find_section(control: cat.Control, skip_section_list: List[str]) -> Tuple[str, str, str]:\n\"\"\"Find next section not in list.\"\"\"\n        if control.parts:\n            for part in control.parts:\n                id_, name, title = ControlInterface._find_section_info(part, skip_section_list)\n                if id_:\n                    return id_, name, title\n        return '', '', ''\n\n    @staticmethod\n    def strip_to_make_ncname(label: str) -> str:\n\"\"\"Strip chars to conform with NCNAME regex.\"\"\"\n        orig_label = label\n        # make sure first char is allowed\n        while label and label[0] not in const.NCNAME_UTF8_FIRST_CHAR_OPTIONS:\n            label = label[1:]\n        new_label = label[:1]\n        # now check remaining chars\n        if len(label) > 1:\n            for ii in range(1, len(label)):\n                if label[ii] in const.NCNAME_UTF8_OTHER_CHAR_OPTIONS:\n                    new_label += label[ii]\n        # do final check to confirm it is NCNAME\n        match = re.search(const.NCNAME_REGEX, new_label)\n        if not match:\n            raise TrestleError(f'Unable to convert label {orig_label} to NCNAME format.')\n        return new_label\n\n    @staticmethod\n    def get_prop(item: TypeWithProps, prop_name: str, default: Optional[str] = None) -> str:\n\"\"\"Get the property with that name or return empty string.\"\"\"\n        for prop in as_list(item.props):\n            if prop.name.strip().lower() == prop_name.strip().lower():\n                return prop.value.strip()\n        return default if default else ''\n\n    @staticmethod\n    def _delete_prop(part_control: TypeWithProps, prop_name: str) -> None:\n\"\"\"Delete property with that name.\"\"\"\n        # assumes at most one instance\n        names = [prop.name for prop in as_list(part_control.props)]\n        if prop_name in names:\n            index = names.index(prop_name)\n            del part_control.props[index]\n        part_control.props = none_if_empty(part_control.props)\n\n    @staticmethod\n    def _replace_prop(part_control: TypeWithProps, new_prop: common.Property) -> None:\n\"\"\"Delete property with that name if present and insert new one.\"\"\"\n        # assumes at most one instance\n        names = [prop.name for prop in as_list(part_control.props)]\n        if new_prop.name in names:\n            index = names.index(new_prop.name)\n            del part_control.props[index]\n        part_control.props = as_list(part_control.props)\n        part_control.props.append(new_prop)\n\n    @staticmethod\n    def _apply_params_format(param_str: Optional[str], params_format: Optional[str]) -> Optional[str]:\n        if param_str is not None and params_format:\n            if params_format.count('.') > 1:\n                raise TrestleError(\n                    f'Additional text {params_format} '\n                    f'for the parameter format cannot contain multiple dots (.)'\n                )\n            param_str = params_format.replace('.', param_str)\n        return param_str\n\n    @staticmethod\n    def create_statement_id(control_id: str, lower: bool = False) -> str:\n\"\"\"Create the control statement id from the control id.\"\"\"\n        id_ = f'{control_id}_smt'\n        return id_.lower() if lower else id_\n\n    @staticmethod\n    def get_statement_id(control: cat.Control) -> str:\n\"\"\"Find the statement id in the control.\"\"\"\n        for part in as_list(control.parts):\n            if part.name == const.STATEMENT:\n                return part.id\n        return ControlInterface.create_statement_id(control.id)\n\n    @staticmethod\n    def get_sort_id(control: cat.Control, allow_none=False) -> Optional[str]:\n\"\"\"Get the sort-id for the control.\"\"\"\n        for prop in as_list(control.props):\n            if prop.name == const.SORT_ID:\n                return prop.value.strip()\n        return None if allow_none else control.id\n\n    @staticmethod\n    def get_label(item: TypeWithProps) -> str:\n\"\"\"Get the label from the props of a part or control.\"\"\"\n        return ControlInterface.get_prop(item, 'label')\n\n    @staticmethod\n    def get_part_by_id(item: TypeWithParts, id_: str) -> Optional[common.Part]:\n\"\"\"Find the part within this item's list of parts that matches id.\"\"\"\n        for part in as_list(item.parts):\n            if part.id == id_:\n                return part\n            deep_part = ControlInterface.get_part_by_id(part, id_)\n            if deep_part:\n                return deep_part\n        return None\n\n    @staticmethod\n    def get_part(part: common.Part, item_type: str, skip_id: Optional[str]) -> List[Union[str, List[str]]]:\n\"\"\"\n        Find parts with the specified item type, within the given part.\n\n        For a part in a control find the parts in it that match the item_type\n        Return list of string formatted labels and associated descriptive prose\n        \"\"\"\n        items = []\n        if part.name in [const.STATEMENT, item_type]:\n            # the options here are to force the label to be the part.id or the part.label\n            # the label may be of the form (a) while the part.id is ac-1_smt.a.1.a\n            # here we choose the latter and extract the final element\n            label = ControlInterface.get_label(part)\n            label = part.id.split('.')[-1] if not label else label\n            wrapped_label = ControlInterface._wrap_label(label)\n            pad = '' if wrapped_label == '' or not part.prose else ' '\n            prose = '' if part.prose is None else part.prose\n            # top level prose has already been written out, if present\n            # use presence of . in id to tell if this is top level prose\n            if part.id != skip_id:\n                if '\\n*' in prose:\n                    # it is multiline prose\n                    sub_items = []\n                    multi_prose = prose.split('\\n*')\n                    items.append(f'{wrapped_label}{pad}{multi_prose[0]}')\n                    multi_prose.remove(multi_prose[0])\n                    for prose in multi_prose:\n                        sub_items.append(f'{prose}')\n                    items.append(sub_items)\n                else:\n                    items.append(f'{wrapped_label}{pad}{prose}')\n            if part.parts:\n                sub_list = []\n                for prt in part.parts:\n                    sub_list.extend(ControlInterface.get_part(prt, item_type, skip_id))\n                sub_list.append('')\n                items.append(sub_list)\n        return items\n\n    @staticmethod\n    def _get_adds_for_control(profile: prof.Profile, control_id: str) -> List[prof.Add]:\n\"\"\"Get the adds for a given control id from a profile.\"\"\"\n        adds: List[prof.Add] = []\n        if profile.modify:\n            for alter in as_list(profile.modify.alters):\n                if alter.control_id == control_id:\n                    adds.extend(as_list(alter.adds))\n        return adds\n\n    @staticmethod\n    def get_all_add_info(control_id: str, profile: prof.Profile) -> List[PartInfo]:\n\"\"\"Get the adds for a control from a profile by control id.\"\"\"\n        part_infos = []\n        for add in ControlInterface._get_adds_for_control(profile, control_id):\n            # add control level props with no name\n            if add.props:\n                smt_part = add.by_id if add.by_id else ''\n                part_infos.append(PartInfo(name='', prose='', smt_part=smt_part, props=add.props))\n            # add part level props with part name\n            for part in as_list(add.parts):\n                subpart_info = ControlInterface._get_part_and_subpart_info(part, add.by_id)\n                part_infos.append(\n                    PartInfo(\n                        name=part.name, prose=part.prose, smt_part=add.by_id, props=part.props, parts=subpart_info\n                    )\n                )\n        return part_infos\n\n    @staticmethod\n    def _get_part_and_subpart_info(part: common.Part, add_by_id: str) -> List[PartInfo]:\n\"\"\"Get part and its subparts info needed for markdown purposes.\"\"\"\n        part_infos = []\n        for subpart in as_list(part.parts):\n            subpart_info = None\n            if subpart.parts:\n                # Recursively add subparts info\n                subpart_info = ControlInterface._get_part_and_subpart_info(subpart, add_by_id)\n            part_infos.append(\n                PartInfo(\n                    name=subpart.name, prose=subpart.prose, smt_part=add_by_id, props=subpart.props, parts=subpart_info\n                )\n            )\n\n        return part_infos\n\n    @staticmethod\n    def get_section(control: cat.Control, skip_section_list: List[str]) -> Tuple[str, str, str, str]:\n\"\"\"Get sections that are not in the list.\"\"\"\n        id_, name, title = ControlInterface._find_section(control, skip_section_list)\n        if id_:\n            return id_, name, title, ControlInterface.get_control_section_prose(control, name)\n        return '', '', '', ''\n\n    @staticmethod\n    def get_part_prose(control: cat.Control, part_name: str) -> str:\n\"\"\"Get the prose for a named part.\"\"\"\n        prose = ''\n        for part in as_list(control.parts):\n            prose += ControlInterface._get_control_section_part(part, part_name)\n        return prose.strip()\n\n    @staticmethod\n    def setparam_to_param(param_id: str, set_param: prof.SetParameter) -> common.Parameter:\n\"\"\"\n        Convert setparameter to parameter.\n\n        Args:\n            param_id: the id of the parameter\n            set_param: the set_parameter from a profile\n\n        Returns:\n            a Parameter with param_id and content from the SetParameter\n        \"\"\"\n        return common.Parameter(\n            id=param_id, values=set_param.values, select=set_param.select, label=set_param.label, props=set_param.props\n        )\n\n    @staticmethod\n    def uniquify_set_params(set_params: Optional[List[TypeWithParamId]]) -> List[TypeWithParamId]:\n\"\"\"Remove items with same param_id with priority to later items.\"\"\"\n        found_ids: Set[str] = set()\n        unique_list: List[TypeWithParamId] = []\n        for set_param in reversed(as_list(set_params)):\n            if set_param.param_id not in found_ids:\n                unique_list.append(set_param)\n                found_ids.add(set_param.param_id)\n        return list(reversed(unique_list))\n\n    @staticmethod\n    def get_rules_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all rules found in this items props.\"\"\"\n        # rules is dict containing rule_id and description\n        rules_dict = {}\n        name = ''\n        desc = ''\n        id_ = ''\n        rules_props = []\n        for prop in as_list(item.props):\n            if prop.name == const.RULE_ID:\n                name = prop.value\n                id_ = prop.remarks\n                rules_props.append(prop)\n            elif prop.name == const.RULE_DESCRIPTION:\n                desc = prop.value\n                rules_props.append(prop)\n            # grab each pair in case there are multiple pairs\n            # then clear and look for new pair\n            if name and desc:\n                rules_dict[id_] = {'name': name, 'description': desc}\n                name = desc = id_ = ''\n        return rules_dict, rules_props\n\n    @staticmethod\n    def item_has_rules(item: TypeWithProps) -> bool:\n\"\"\"Determine if the item has rules in its props.\"\"\"\n        _, rules_props = ControlInterface.get_rules_dict_from_item(item)\n        return bool(rules_props)\n\n    @staticmethod\n    def get_rule_list_for_item(item: TypeWithProps) -> Tuple[List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to this item from its top level props.\"\"\"\n        props = []\n        rule_list = []\n        for prop in as_list(item.props):\n            if prop.name == const.RULE_ID:\n                rule_list.append(prop.value)\n                props.append(prop)\n        return rule_list, props\n\n    @staticmethod\n    def get_rule_list_for_imp_req(\n        imp_req: ossp.ImplementedRequirement\n    ) -> Tuple[List[str], List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to an imp_req as two lists.\"\"\"\n        comp_rules, rule_props = ControlInterface.get_rule_list_for_item(imp_req)\n        statement_rules = set()\n        for statement in as_list(imp_req.statements):\n            stat_rules, statement_props = ControlInterface.get_rule_list_for_item(statement)\n            statement_rules.update(stat_rules)\n            rule_props.extend(statement_props)\n        return comp_rules, sorted(statement_rules), rule_props\n\n    @staticmethod\n    def get_params_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all params found in this item with rule_id as key.\"\"\"\n        # id, description, options - where options is a string containing comma-sep list of items\n        # params is dict with rule_id as key and value contains: param_name, description and choices\n        params: Dict[str, List[Dict[str, str]]] = {}\n        props = []\n        for prop in as_list(item.props):\n            if const.PARAMETER_ID in prop.name:\n                rule_id = prop.remarks\n                param_name = prop.value\n                # rule already exists in parameters dict\n                if rule_id in params.keys():\n                    existing_param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                    if existing_param is not None:\n                        raise TrestleError(f'Param id for rule {rule_id} already exists')\n                    else:\n                        # append a new parameter for the current rule\n                        params[rule_id].append({'name': param_name})\n                else:\n                    # create new param for this rule for the first parameter\n                    params[rule_id] = [{'name': param_name}]\n                props.append(prop)\n            elif const.PARAMETER_DESCRIPTION in prop.name:\n                rule_id = prop.remarks\n                if rule_id in params:\n                    param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                    param['description'] = prop.value\n                    props.append(prop)\n                else:\n                    raise TrestleError(f'Param description for rule {rule_id} found with no param_id')\n            elif const.PARAMETER_VALUE_ALTERNATIVES in prop.name:\n                rule_id = prop.remarks\n                if rule_id in params:\n                    param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                    param['options'] = prop.value\n                    props.append(prop)\n                else:\n                    raise TrestleError(f'Param options for rule {rule_id} found with no param_id')\n        new_params = {}\n        for rule_id, rule_params in params.items():\n            new_params[rule_id] = []\n            for param in rule_params:\n                if 'name' not in param:\n                    logger.warning(f'Parameter for rule_id {rule_id} has no matching name.  Ignoring the param.')\n                else:\n                    param['description'] = param.get('description', '')\n                    param['options'] = param.get('options', '')\n                    new_params[rule_id].append(param)\n        return new_params, props\n\n    @staticmethod\n    def get_rules_and_params_dict_from_item(\n        item: TypeWithProps\n    ) -> Tuple[Dict[str, Dict[str, str]], Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get the rule dict and params dict from item with props.\"\"\"\n        rules_dict, rules_props = ControlInterface.get_rules_dict_from_item(item)\n        params_dict, params_props = ControlInterface.get_params_dict_from_item(item)\n        rules_props.extend(params_props)\n        return rules_dict, params_dict, rules_props\n\n    @staticmethod\n    def get_set_params_from_item(\n        item: Union[comp.ControlImplementation, comp.ImplementedRequirement]\n    ) -> Dict[str, comp.SetParameter]:\n\"\"\"Get set params that have values from control implementation or imp req.\"\"\"\n        return {\n            set_param.param_id: set_param\n            for set_param in as_filtered_list(item.set_parameters, lambda i: i.values)\n        }\n\n    @staticmethod\n    def merge_props(dest: Optional[List[common.Property]],\n                    src: Optional[List[common.Property]]) -> List[common.Property]:\n\"\"\"Merge a source list of properties into a destination list.\"\"\"\n        if not src:\n            return dest\n        new_props: List[common.Property] = []\n        src_map = {prop.name: prop for prop in src}\n        dest_map = {prop.name: prop for prop in dest}\n        all_names = set(src_map.keys()).union(dest_map.keys())\n        for name in sorted(all_names):\n            if name in src_map and name not in dest_map:\n                new_props.append(src_map[name])\n            elif name in dest_map and name not in src_map:\n                new_props.append(dest_map[name])\n            else:\n                new_prop = dest_map[name]\n                src_prop = src_map[name]\n                new_prop.class_ = src_prop.class_ if src_prop.class_ else new_prop.class_\n                new_prop.ns = src_prop.ns if src_prop.ns else new_prop.ns\n                new_prop.remarks = src_prop.remarks if src_prop.remarks else new_prop.remarks\n                new_prop.uuid = src_prop.uuid if src_prop.uuid else new_prop.uuid\n                new_prop.value = src_prop.value\n                new_props.append(new_prop)\n        return new_props\n\n    @staticmethod\n    def merge_part(dest: common.Part, src: common.Part) -> common.Part:\n\"\"\"Merge a source part into the destination part.\"\"\"\n        dest.name = src.name if src.name else dest.name\n        dest.ns = src.ns if src.ns else dest.ns\n        dest.props = none_if_empty(ControlInterface.merge_props(dest.props, src.props))\n        dest.prose = src.prose\n        dest.title = src.title if src.title else dest.title\n        ControlInterface.merge_parts(dest, src)\n        return dest\n\n    @staticmethod\n    def merge_parts(dest: TypeWithParts, src: TypeWithParts) -> None:\n\"\"\"Merge the parts from the source into the destination.\"\"\"\n        if not dest.parts:\n            dest.parts = src.parts\n        elif not src.parts:\n            dest.parts = None\n        else:\n            new_parts: List[common.Part] = []\n            dest_map = {part.id: part for part in dest.parts}\n            for src_part in src.parts:\n                dest_part = dest_map.get(src_part.id, None)\n                if not dest_part:\n                    new_parts.append(src_part)\n                else:\n                    new_part = ControlInterface.merge_part(dest_part, src_part)\n                    if new_part:\n                        new_parts.append(new_part)\n            dest.parts = new_parts\n\n    @staticmethod\n    def merge_dicts_deep(\n        dest: Dict[Any, Any],\n        src: Dict[Any, Any],\n        overwrite_header_values: bool,\n        depth: int = 0,\n        level: int = 0\n    ) -> None:\n\"\"\"\n        Merge dict src into dest.\n\n        New items are always added from src to dest.\n        Items present in both will be overriden dest if overwrite_header_values is True.\n        \"\"\"\n        for key in src.keys():\n            if key in dest:\n                if depth and level == depth:\n                    if overwrite_header_values:\n                        dest[key] = src[key]\n                    continue\n                # if they are both dicts, recurse\n                if isinstance(dest[key], dict) and isinstance(src[key], dict):\n                    ControlInterface.merge_dicts_deep(dest[key], src[key], overwrite_header_values, depth, level + 1)\n                # if they are both lists, add any item that is not already in the list\n                elif isinstance(dest[key], list) and isinstance(src[key], list):\n                    for item in src[key]:\n                        if item not in dest[key]:\n                            dest[key].append(item)\n                # otherwise override dest if needed\n                elif overwrite_header_values:\n                    dest[key] = src[key]\n            else:\n                # if the item was not already in dest, add it from src\n                dest[key] = src[key]\n\n    @staticmethod\n    def is_withdrawn(control: cat.Control) -> bool:\n\"\"\"\n        Determine if control is marked Withdrawn.\n\n        Args:\n            control: The control that may be marked withdrawn.\n\n        Returns:\n            True if marked withdrawn, false otherwise.\n\n        This is determined by property with name 'status' with value 'Withdrawn'.\n        \"\"\"\n        for _ in as_filtered_list(\n                control.props,\n                lambda p: strip_lower_equals(p.name, 'status') and strip_lower_equals(p.value, 'withdrawn')):\n            return True\n        return False\n\n    @staticmethod\n    def _setparam_values_as_str(set_param: comp.SetParameter) -> str:\n\"\"\"Convert values to string.\"\"\"\n        out_str = ''\n        for value in as_list(set_param.values):\n            value_str = string_from_root(value)\n            if value_str:\n                if out_str:\n                    out_str += ', '\n                out_str += value_str\n        return out_str\n\n    @staticmethod\n    def _param_values_as_str_list(param: common.Parameter) -> List[str]:\n\"\"\"Convert param values to list of strings.\"\"\"\n        return as_list(param.values)\n\n    @staticmethod\n    def _param_values_as_str(param: common.Parameter, brackets=False) -> Optional[str]:\n\"\"\"Convert param values to string with optional brackets.\"\"\"\n        if not param.values:\n            return None\n        values_str = ', '.join(ControlInterface._param_values_as_str_list(param))\n        return f'[{values_str}]' if brackets else values_str\n\n    @staticmethod\n    def _param_selection_as_str(param: common.Parameter, verbose: bool = False, brackets: bool = False) -> str:\n\"\"\"Convert parameter selection to str.\"\"\"\n        if param.select and param.select.choice:\n            how_many_str = ''\n            # if all values are specified there is no how_many string and parens are dropped.  See ac-2.2\n            if param.select.how_many:\n                how_many_str = ' (one)' if param.select.how_many == const.ONE else ' (one or more)'\n            choices_str = '; '.join(as_list(param.select.choice))\n            choices_str = f'[{choices_str}]' if brackets else choices_str\n            choices_str = f'Selection{how_many_str}: {choices_str}' if verbose else choices_str\n            return choices_str\n        return ''\n\n    @staticmethod\n    def _param_as_aggregated_value(\n        param: common.Parameter,\n        param_dict: Dict[str, common.Parameter],\n        verbose: bool = False,\n        brackets: bool = False\n    ) -> str:\n\"\"\"Convert parameter aggregation to str.\"\"\"\n        # review is an aggregated parameter\n        if const.AGGREGATES in [prop.name for prop in as_list(param.props)]:\n            aggregated_values = ''\n            for prop in as_list(param.props):\n                if prop.value not in param_dict:\n                    continue\n                aggregated_values += ', '.join(as_list(param_dict[prop.value].values)) + ', '\n            return aggregated_values[:-2]\n        return ''\n\n    @staticmethod\n    def _param_label_choices_as_str(param: common.Parameter, verbose: bool = False, brackets: bool = False) -> str:\n\"\"\"Convert param label or choices to string, using choices if present.\"\"\"\n        choices = ControlInterface._param_selection_as_str(param, verbose, brackets)\n        text = choices if choices else param.label\n        text = text if text else param.id\n        return text\n\n    @staticmethod\n    def _param_values_assignment_str(\n        param: common.Parameter,\n        param_dict: Dict[str, common.Parameter],\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> str:\n\"\"\"Convert param values, label or choices to string.\"\"\"\n        # use values if present\n        param_str = ControlInterface._param_values_as_str(param, False)\n        if param_str and value_assigned_prefix:\n            param_str = f'{value_assigned_prefix} {param_str}'\n        # otherwise use param selection if present\n        if not param_str:\n            param_str = ControlInterface._param_selection_as_str(param, True, False)\n        # otherwise use param aggregated values if present\n        if not param_str:\n            param_str = ControlInterface._param_as_aggregated_value(param, param_dict, True, False)\n        # finally use label and param_id as fallbacks\n        if not param_str:\n            param_str = param.label if param.label else param.id\n            if value_not_assigned_prefix:\n                param_str = f'{value_not_assigned_prefix} {param_str}'\n        return f'{param_str}'\n\n    @staticmethod\n    def _param_labels_assignment_str(\n        param: common.Parameter,\n        label_prefix: Optional[str] = None,\n    ) -> str:\n\"\"\"Convert param label or choices to string.\"\"\"\n        # use values if present\n        param_str = ControlInterface._param_selection_as_str(param, True, False)\n        # finally use label and param_id as fallbacks\n        if not param_str:\n            param_str = param.label if param.label else param.id\n            if label_prefix:\n                param_str = f'{label_prefix} {param_str}'\n        return f'{param_str}'\n\n    @staticmethod\n    def param_to_str(\n        param: common.Parameter,\n        param_rep: ParameterRep,\n        verbose: bool = False,\n        brackets: bool = False,\n        params_format: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None,\n        param_dict: Dict[str, common.Parameter] = None\n    ) -> Optional[str]:\n\"\"\"\n        Convert parameter to string based on best available representation.\n\n        Args:\n            param: the parameter to convert\n            param_rep: how to represent the parameter\n            verbose: provide verbose text for selection choices\n            brackets: add brackets around the lists of items\n            params_format: a string containing a single dot that represents a form of highlighting around the param\n            value_assigned_prefix: string to place before the parameter string if a value was assigned\n            value_not_assigned_prefix: string to place before the parameter string if value not assigned\n\n        Returns:\n            formatted string or None\n        \"\"\"\n        param_str = None\n        if param_rep == ParameterRep.VALUE_OR_STRING_NONE:\n            param_str = ControlInterface._param_values_as_str(param)\n            param_str = param_str if param_str else 'None'\n        elif param_rep == ParameterRep.LABEL_OR_CHOICES:\n            param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n        elif param_rep == ParameterRep.VALUE_OR_LABEL_OR_CHOICES:\n            param_str = ControlInterface._param_values_as_str(param)\n            if not param_str:\n                param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n        elif param_rep == ParameterRep.VALUE_OR_EMPTY_STRING:\n            param_str = ControlInterface._param_values_as_str(param, brackets)\n            if not param_str:\n                param_str = ''\n        elif param_rep == ParameterRep.ASSIGNMENT_FORM:\n            param_str = ControlInterface._param_values_assignment_str(\n                param, param_dict, value_assigned_prefix, value_not_assigned_prefix\n            )\n            if not param_str:\n                param_str = ''\n        elif param_rep == ParameterRep.LABEL_FORM:\n            param_str = ControlInterface._param_labels_assignment_str(param, value_not_assigned_prefix)\n            if not param_str:\n                param_str = ''\n        return ControlInterface._apply_params_format(param_str, params_format)\n\n    @staticmethod\n    def get_control_param_dict(control: cat.Control, values_only: bool) -> Dict[str, common.Parameter]:\n\"\"\"\n        Create mapping of param id's to params for params in the control.\n\n        Args:\n            control: the control containing params of interest\n            values_only: only add params to the dict that have actual values\n\n        Returns:\n            Dictionary of param_id mapped to param\n\n        Notes:\n            Warning is given if there is a parameter with no ID\n        \"\"\"\n        param_dict: Dict[str, common.Parameter] = {}\n        for param in as_list(control.params):\n            if not param.id:\n                logger.warning(f'Control {control.id} has parameter with no id.  Ignoring.')\n            if param.values or not values_only:\n                param_dict[param.id] = param\n        return param_dict\n\n    @staticmethod\n    def _replace_ids_with_text(\n        prose: str,\n        param_rep: ParameterRep,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> str:\n\"\"\"Find all instances of param_ids in prose and replace each with corresponding parameter representation.\n\n        Need to check all values in dict for a match\n        Reject matches where the string has an adjacent alphanumeric char: param_1 and param_10 or aparam_1\n        \"\"\"\n        for param in param_dict.values():\n            if param.id not in prose:\n                continue\n            # create the replacement text for the param_id\n            param_str = ControlInterface.param_to_str(\n                param, param_rep, False, False, params_format, value_assigned_prefix, value_not_assigned_prefix\n            )\n            # non-capturing groups are odd in re.sub so capture all 3 groups and replace the middle one\n            pattern = r'(^|[^a-zA-Z0-9_])' + param.id + r'($|[^a-zA-Z0-9_])'\n            prose = re.sub(pattern, r'\\1' + param_str + r'\\2', prose)\n        return prose\n\n    @staticmethod\n    def _replace_params(\n        text: str,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> str:\n\"\"\"\n        Replace params found in moustaches with values from the param_dict.\n\n        A single line of prose may contain multiple moustaches.\n        \"\"\"\n        # first check if there are any moustache patterns in the text\n        if param_rep == ParameterRep.LEAVE_MOUSTACHE:\n            return text\n        orig_text = text\n        staches: List[str] = re.findall(r'{{.*?}}', text)\n        if not staches:\n            return text\n        # now have list of all staches including braces, e.g. ['{{foo}}', '{{bar}}']\n        # clean the staches so they just have the param ids\n        param_ids = []\n        for stache in staches:\n            # remove braces so these are just param_ids but may have extra chars\n            stache_contents = stache[2:(-2)]\n            param_id = stache_contents.replace('insert: param,', '').strip()\n            param_ids.append(param_id)\n\n        # now replace original stache text with param values\n        for i, _ in enumerate(staches):\n            # A moustache may refer to a param_id not listed in the control's params\n            if param_ids[i] not in param_dict:\n                if show_value_warnings:\n                    logger.warning(f'Control prose references param {param_ids[i]} not set in the control: {staches}')\n            elif param_dict[param_ids[i]] is not None:\n                param = param_dict[param_ids[i]]\n                param_str = ControlInterface.param_to_str(\n                    param,\n                    param_rep,\n                    False,\n                    False,\n                    params_format,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix,\n                    param_dict\n                )\n                text = text.replace(staches[i], param_str, 1).strip()\n                if show_value_warnings and param_rep != ParameterRep.LABEL_OR_CHOICES and not param.values:\n                    # verifies the current parameter is not an aggregated parameter to throw a warning\n                    if const.AGGREGATES not in [prop.name for prop in as_list(param.props)]:\n                        logger.warning(f'Parameter {param_id} has no values and was referenced by prose.')\n            elif show_value_warnings:\n                logger.warning(f'Control prose references param {param_ids[i]} with no specified value.')\n        # there may be staches remaining that we can't replace if not in param_dict\n        if text != orig_text:\n            while True:\n                new_text = ControlInterface._replace_params(\n                    text,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n                if new_text == text:\n                    break\n                text = new_text\n        return text\n\n    @staticmethod\n    def _replace_part_prose(\n        control: cat.Control,\n        part: common.Part,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Replace the part prose according to set_param.\"\"\"\n        if part.prose is not None:\n            fixed_prose = ControlInterface._replace_params(\n                part.prose,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n            # change the prose in the control itself\n            part.prose = fixed_prose\n        for prt in as_list(part.parts):\n            ControlInterface._replace_part_prose(\n                control,\n                prt,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n        for sub_control in as_list(control.controls):\n            for prt in as_list(sub_control.parts):\n                ControlInterface._replace_part_prose(\n                    sub_control,\n                    prt,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n\n    @staticmethod\n    def _replace_param_choices(\n        param: common.Parameter,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str],\n        param_rep: ParameterRep,\n        show_value_warnings: bool,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Set values for all choices param that refer to params with values.\"\"\"\n        if param.select:\n            new_choices: List[str] = []\n            for choice in as_list(param.select.choice):\n                new_choice = ControlInterface._replace_params(\n                    choice,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n                new_choices.append(new_choice)\n            param.select.choice = new_choices\n\n    @staticmethod\n    def replace_control_prose(\n        control: cat.Control,\n        param_dict: Dict[str, common.Parameter],\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Replace the control prose according to set_param.\"\"\"\n        # first replace all choices that reference parameters\n        # note that in ASSIGNMENT_FORM each choice with a parameter will end up as [Assignment: value]\n        for param in as_list(control.params):\n            ControlInterface._replace_param_choices(\n                param,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n        for part in as_list(control.parts):\n            if part.prose is not None:\n                fixed_prose = ControlInterface._replace_params(\n                    part.prose,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n                # change the prose in the control itself\n                part.prose = fixed_prose\n            for prt in as_list(part.parts):\n                ControlInterface._replace_part_prose(\n                    control,\n                    prt,\n                    param_dict,\n                    params_format,\n                    param_rep,\n                    show_value_warnings,\n                    value_assigned_prefix,\n                    value_not_assigned_prefix\n                )\n\n    @staticmethod\n    def bad_header(header: str) -> bool:\n\"\"\"Return true if header format is bad.\"\"\"\n        if not header or header[0] != '#':\n            return True\n        n = len(header)\n        if n < 2:\n            return True\n        for ii in range(1, n):\n            if header[ii] == ' ':\n                return False\n            if header[ii] != '#':\n                return True\n        return True\n\n    @staticmethod\n    def get_component_by_name(comp_def: comp.ComponentDefinition, comp_name: str) -> Optional[comp.DefinedComponent]:\n\"\"\"Get the component with this name from the comp_def.\"\"\"\n        for sub_comp in as_list(comp_def.components):\n            if sub_comp.title == comp_name:\n                return sub_comp\n        return None\n\n    @staticmethod\n    def get_status_from_props(item: TypeWithProps) -> common.ImplementationStatus:\n\"\"\"Get the status of an item from its props.\"\"\"\n        status = common.ImplementationStatus(state=const.STATUS_PLANNED)\n        for prop in as_list(item.props):\n            if prop.name == const.IMPLEMENTATION_STATUS:\n                status = ControlInterface._prop_as_status(prop)\n                break\n        return status\n\n    @staticmethod\n    def clean_props(\n        props: Optional[List[common.Property]],\n        remove_imp_status: bool = True,\n        remove_all_rule_info: bool = False\n    ) -> List[common.Property]:\n\"\"\"Remove duplicate props and implementation status.\"\"\"\n        new_props: List[common.Property] = []\n        found_props: Set[Tuple[str, str, str, str]] = set()\n        rule_tag_list = [\n            const.RULE_DESCRIPTION, const.RULE_ID, const.PARAMETER_DESCRIPTION, const.PARAMETER_VALUE_ALTERNATIVES\n        ]\n        # reverse the list so the latest items are kept\n        for prop in reversed(as_list(props)):\n            prop_tuple = (prop.name, as_string(prop.value), as_string(prop.ns), prop.remarks)\n            if prop_tuple in found_props or (prop.name == const.IMPLEMENTATION_STATUS and remove_imp_status):\n                continue\n            if remove_all_rule_info and prop.name in rule_tag_list:\n                continue\n            found_props.add(prop_tuple)\n            new_props.append(prop)\n        new_props.reverse()\n        return new_props\n\n    @staticmethod\n    def cull_props_by_rules(props: Optional[List[common.Property]], rules: List[str]) -> List[common.Property]:\n\"\"\"Cull properties to the ones needed by rules.\"\"\"\n        needed_rule_ids: Set[str] = set()\n        culled_props: List[common.Property] = []\n        for prop in as_list(props):\n            if prop.value in rules and prop.remarks:\n                needed_rule_ids.add(prop.remarks)\n        for prop in as_list(props):\n            if prop.value in rules or prop.remarks in needed_rule_ids:\n                culled_props.append(prop)\n        return culled_props\n\n    @staticmethod\n    def _status_as_prop(status: common.ImplementationStatus) -> common.Property:\n\"\"\"Convert status to property.\"\"\"\n        return common.Property(name=const.IMPLEMENTATION_STATUS, value=status.state, remarks=status.remarks)\n\n    @staticmethod\n    def _prop_as_status(prop: common.Property) -> common.ImplementationStatus:\n\"\"\"Convert property to status.\"\"\"\n        return common.ImplementationStatus(state=prop.value, remarks=prop.remarks)\n\n    @staticmethod\n    def insert_status_in_props(item: TypeWithProps, status: common.ImplementationStatus) -> None:\n\"\"\"Insert status content into props of the item.\"\"\"\n        prop = ControlInterface._status_as_prop(status)\n        ControlInterface._replace_prop(item, prop)\n\n    @staticmethod\n    def _copy_status_in_props(dest: TypeWithProps, src: TypeWithProps) -> None:\n\"\"\"Copy status in props from one object to another.\"\"\"\n        status = ControlInterface.get_status_from_props(src)\n        ControlInterface.insert_status_in_props(dest, status)\n\n    @staticmethod\n    def insert_imp_req_into_component(\n        component: comp.DefinedComponent,\n        new_imp_req: comp.ImplementedRequirement,\n        profile_title: str,\n        trestle_root: pathlib.Path\n    ) -> None:\n\"\"\"\n        Insert imp req into component by matching source title and control id to existing imp req.\n\n        Args:\n            component: The defined component receiving the imp_req\n            new_imp_req: The new imp_req being added\n            profile_title: The title of the source profile for the control implementation containing the imp_req\n\n        Notes:\n            Inserts the imp_req on the first match found.  Note it is possible two control implementations could\n            have the same source and specify the same control\n        \"\"\"\n        for control_imp in as_list(component.control_implementations):\n            _, control_imp_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)\n            control_imp_rule_param_ids = [\n                param['name'] for params in control_imp_param_dict.values() for param in params\n            ]\n            if profile_title != ModelUtils.get_title_from_model_uri(trestle_root, control_imp.source):\n                continue\n            for imp_req in as_list(control_imp.implemented_requirements):\n                if imp_req.control_id != new_imp_req.control_id:\n                    continue\n                _, imp_req_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(imp_req)\n                imp_req_rule_param_ids = [param['name'] for params in imp_req_param_dict.values() for param in params]\n                status = ControlInterface.get_status_from_props(new_imp_req)\n                ControlInterface.insert_status_in_props(imp_req, status)\n                imp_req.description = new_imp_req.description\n                statement_dict = {stat.statement_id: stat for stat in as_list(imp_req.statements)}\n                # update set parameter values with values from markdown - but only for rule param vals\n                for set_param in as_list(new_imp_req.set_parameters):\n                    if set_param.param_id not in (control_imp_rule_param_ids + imp_req_rule_param_ids):\n                        continue\n                    found = False\n                    for dest_param in as_list(imp_req.set_parameters):\n                        if dest_param.param_id != set_param.param_id:\n                            continue\n                        dest_param.values = set_param.values\n                        found = True\n                        break\n                    # if rule parameter val was not already set by a set_param, make new set_param for it\n                    if found:\n                        continue\n                    # but first check if the parameter was already set with the same value in the control_imp\n                    # if so we don't need to insert a new set_param in imp_req\n                    for dest_param in as_list(control_imp.set_parameters):\n                        if dest_param.param_id != set_param.param_id:\n                            continue\n                        if dest_param.values == set_param.values:\n                            found = True\n                            break\n                    if found:\n                        continue\n                    imp_req.set_parameters = as_list(imp_req.set_parameters)\n                    imp_req.set_parameters.append(\n                        comp.SetParameter(param_id=set_param.param_id, values=set_param.values)\n                    )\n                new_statements: List[comp.Statement] = []\n                for statement in as_list(new_imp_req.statements):\n                    # get the original version of the statement if available, or use new one\n                    stat = statement_dict.get(statement.statement_id, statement)\n                    # update the description and status from markdown\n                    stat.description = statement.description\n                    ControlInterface._copy_status_in_props(stat, statement)\n                    new_statements.append(stat)\n                imp_req.statements = none_if_empty(new_statements)\n                return\n        logger.warning(\n            f'Unable to add imp req for component {component.title} control {new_imp_req.control_id} and source: {profile_title}'  # noqa E501\n        )\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.bad_header","title":"bad_header(header) staticmethod","text":"

                                                                            Return true if header format is bad.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef bad_header(header: str) -> bool:\n\"\"\"Return true if header format is bad.\"\"\"\n    if not header or header[0] != '#':\n        return True\n    n = len(header)\n    if n < 2:\n        return True\n    for ii in range(1, n):\n        if header[ii] == ' ':\n            return False\n        if header[ii] != '#':\n            return True\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.clean_props","title":"clean_props(props, remove_imp_status=True, remove_all_rule_info=False) staticmethod","text":"

                                                                            Remove duplicate props and implementation status.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef clean_props(\n    props: Optional[List[common.Property]],\n    remove_imp_status: bool = True,\n    remove_all_rule_info: bool = False\n) -> List[common.Property]:\n\"\"\"Remove duplicate props and implementation status.\"\"\"\n    new_props: List[common.Property] = []\n    found_props: Set[Tuple[str, str, str, str]] = set()\n    rule_tag_list = [\n        const.RULE_DESCRIPTION, const.RULE_ID, const.PARAMETER_DESCRIPTION, const.PARAMETER_VALUE_ALTERNATIVES\n    ]\n    # reverse the list so the latest items are kept\n    for prop in reversed(as_list(props)):\n        prop_tuple = (prop.name, as_string(prop.value), as_string(prop.ns), prop.remarks)\n        if prop_tuple in found_props or (prop.name == const.IMPLEMENTATION_STATUS and remove_imp_status):\n            continue\n        if remove_all_rule_info and prop.name in rule_tag_list:\n            continue\n        found_props.add(prop_tuple)\n        new_props.append(prop)\n    new_props.reverse()\n    return new_props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.create_statement_id","title":"create_statement_id(control_id, lower=False) staticmethod","text":"

                                                                            Create the control statement id from the control id.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef create_statement_id(control_id: str, lower: bool = False) -> str:\n\"\"\"Create the control statement id from the control id.\"\"\"\n    id_ = f'{control_id}_smt'\n    return id_.lower() if lower else id_\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.cull_props_by_rules","title":"cull_props_by_rules(props, rules) staticmethod","text":"

                                                                            Cull properties to the ones needed by rules.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef cull_props_by_rules(props: Optional[List[common.Property]], rules: List[str]) -> List[common.Property]:\n\"\"\"Cull properties to the ones needed by rules.\"\"\"\n    needed_rule_ids: Set[str] = set()\n    culled_props: List[common.Property] = []\n    for prop in as_list(props):\n        if prop.value in rules and prop.remarks:\n            needed_rule_ids.add(prop.remarks)\n    for prop in as_list(props):\n        if prop.value in rules or prop.remarks in needed_rule_ids:\n            culled_props.append(prop)\n    return culled_props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_all_add_info","title":"get_all_add_info(control_id, profile) staticmethod","text":"

                                                                            Get the adds for a control from a profile by control id.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_all_add_info(control_id: str, profile: prof.Profile) -> List[PartInfo]:\n\"\"\"Get the adds for a control from a profile by control id.\"\"\"\n    part_infos = []\n    for add in ControlInterface._get_adds_for_control(profile, control_id):\n        # add control level props with no name\n        if add.props:\n            smt_part = add.by_id if add.by_id else ''\n            part_infos.append(PartInfo(name='', prose='', smt_part=smt_part, props=add.props))\n        # add part level props with part name\n        for part in as_list(add.parts):\n            subpart_info = ControlInterface._get_part_and_subpart_info(part, add.by_id)\n            part_infos.append(\n                PartInfo(\n                    name=part.name, prose=part.prose, smt_part=add.by_id, props=part.props, parts=subpart_info\n                )\n            )\n    return part_infos\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_component_by_name","title":"get_component_by_name(comp_def, comp_name) staticmethod","text":"

                                                                            Get the component with this name from the comp_def.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_component_by_name(comp_def: comp.ComponentDefinition, comp_name: str) -> Optional[comp.DefinedComponent]:\n\"\"\"Get the component with this name from the comp_def.\"\"\"\n    for sub_comp in as_list(comp_def.components):\n        if sub_comp.title == comp_name:\n            return sub_comp\n    return None\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_control_param_dict","title":"get_control_param_dict(control, values_only) staticmethod","text":"

                                                                            Create mapping of param id's to params for params in the control.

                                                                            Parameters:

                                                                            Name Type Description Default control cat.Control

                                                                            the control containing params of interest

                                                                            required values_only bool

                                                                            only add params to the dict that have actual values

                                                                            required

                                                                            Returns:

                                                                            Type Description Dict[str, common.Parameter]

                                                                            Dictionary of param_id mapped to param

                                                                            Notes

                                                                            Warning is given if there is a parameter with no ID

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_control_param_dict(control: cat.Control, values_only: bool) -> Dict[str, common.Parameter]:\n\"\"\"\n    Create mapping of param id's to params for params in the control.\n\n    Args:\n        control: the control containing params of interest\n        values_only: only add params to the dict that have actual values\n\n    Returns:\n        Dictionary of param_id mapped to param\n\n    Notes:\n        Warning is given if there is a parameter with no ID\n    \"\"\"\n    param_dict: Dict[str, common.Parameter] = {}\n    for param in as_list(control.params):\n        if not param.id:\n            logger.warning(f'Control {control.id} has parameter with no id.  Ignoring.')\n        if param.values or not values_only:\n            param_dict[param.id] = param\n    return param_dict\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_control_section_prose","title":"get_control_section_prose(control, section_name) staticmethod","text":"

                                                                            Get the prose for the control section.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_control_section_prose(control: cat.Control, section_name: str) -> str:\n\"\"\"Get the prose for the control section.\"\"\"\n    prose = ''\n    if control.parts:\n        for part in control.parts:\n            prose = ControlInterface._gap_join(\n                prose, ControlInterface._get_control_section_part(part, section_name)\n            )\n    return prose\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_label","title":"get_label(item) staticmethod","text":"

                                                                            Get the label from the props of a part or control.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_label(item: TypeWithProps) -> str:\n\"\"\"Get the label from the props of a part or control.\"\"\"\n    return ControlInterface.get_prop(item, 'label')\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_params_dict_from_item","title":"get_params_dict_from_item(item) staticmethod","text":"

                                                                            Get all params found in this item with rule_id as key.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_params_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all params found in this item with rule_id as key.\"\"\"\n    # id, description, options - where options is a string containing comma-sep list of items\n    # params is dict with rule_id as key and value contains: param_name, description and choices\n    params: Dict[str, List[Dict[str, str]]] = {}\n    props = []\n    for prop in as_list(item.props):\n        if const.PARAMETER_ID in prop.name:\n            rule_id = prop.remarks\n            param_name = prop.value\n            # rule already exists in parameters dict\n            if rule_id in params.keys():\n                existing_param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                if existing_param is not None:\n                    raise TrestleError(f'Param id for rule {rule_id} already exists')\n                else:\n                    # append a new parameter for the current rule\n                    params[rule_id].append({'name': param_name})\n            else:\n                # create new param for this rule for the first parameter\n                params[rule_id] = [{'name': param_name}]\n            props.append(prop)\n        elif const.PARAMETER_DESCRIPTION in prop.name:\n            rule_id = prop.remarks\n            if rule_id in params:\n                param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                param['description'] = prop.value\n                props.append(prop)\n            else:\n                raise TrestleError(f'Param description for rule {rule_id} found with no param_id')\n        elif const.PARAMETER_VALUE_ALTERNATIVES in prop.name:\n            rule_id = prop.remarks\n            if rule_id in params:\n                param = next((prm for prm in params[rule_id] if prm['name'] == param_name), None)\n                param['options'] = prop.value\n                props.append(prop)\n            else:\n                raise TrestleError(f'Param options for rule {rule_id} found with no param_id')\n    new_params = {}\n    for rule_id, rule_params in params.items():\n        new_params[rule_id] = []\n        for param in rule_params:\n            if 'name' not in param:\n                logger.warning(f'Parameter for rule_id {rule_id} has no matching name.  Ignoring the param.')\n            else:\n                param['description'] = param.get('description', '')\n                param['options'] = param.get('options', '')\n                new_params[rule_id].append(param)\n    return new_params, props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_part","title":"get_part(part, item_type, skip_id) staticmethod","text":"

                                                                            Find parts with the specified item type, within the given part.

                                                                            For a part in a control find the parts in it that match the item_type Return list of string formatted labels and associated descriptive prose

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_part(part: common.Part, item_type: str, skip_id: Optional[str]) -> List[Union[str, List[str]]]:\n\"\"\"\n    Find parts with the specified item type, within the given part.\n\n    For a part in a control find the parts in it that match the item_type\n    Return list of string formatted labels and associated descriptive prose\n    \"\"\"\n    items = []\n    if part.name in [const.STATEMENT, item_type]:\n        # the options here are to force the label to be the part.id or the part.label\n        # the label may be of the form (a) while the part.id is ac-1_smt.a.1.a\n        # here we choose the latter and extract the final element\n        label = ControlInterface.get_label(part)\n        label = part.id.split('.')[-1] if not label else label\n        wrapped_label = ControlInterface._wrap_label(label)\n        pad = '' if wrapped_label == '' or not part.prose else ' '\n        prose = '' if part.prose is None else part.prose\n        # top level prose has already been written out, if present\n        # use presence of . in id to tell if this is top level prose\n        if part.id != skip_id:\n            if '\\n*' in prose:\n                # it is multiline prose\n                sub_items = []\n                multi_prose = prose.split('\\n*')\n                items.append(f'{wrapped_label}{pad}{multi_prose[0]}')\n                multi_prose.remove(multi_prose[0])\n                for prose in multi_prose:\n                    sub_items.append(f'{prose}')\n                items.append(sub_items)\n            else:\n                items.append(f'{wrapped_label}{pad}{prose}')\n        if part.parts:\n            sub_list = []\n            for prt in part.parts:\n                sub_list.extend(ControlInterface.get_part(prt, item_type, skip_id))\n            sub_list.append('')\n            items.append(sub_list)\n    return items\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_part_by_id","title":"get_part_by_id(item, id_) staticmethod","text":"

                                                                            Find the part within this item's list of parts that matches id.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_part_by_id(item: TypeWithParts, id_: str) -> Optional[common.Part]:\n\"\"\"Find the part within this item's list of parts that matches id.\"\"\"\n    for part in as_list(item.parts):\n        if part.id == id_:\n            return part\n        deep_part = ControlInterface.get_part_by_id(part, id_)\n        if deep_part:\n            return deep_part\n    return None\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_part_prose","title":"get_part_prose(control, part_name) staticmethod","text":"

                                                                            Get the prose for a named part.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_part_prose(control: cat.Control, part_name: str) -> str:\n\"\"\"Get the prose for a named part.\"\"\"\n    prose = ''\n    for part in as_list(control.parts):\n        prose += ControlInterface._get_control_section_part(part, part_name)\n    return prose.strip()\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_prop","title":"get_prop(item, prop_name, default=None) staticmethod","text":"

                                                                            Get the property with that name or return empty string.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_prop(item: TypeWithProps, prop_name: str, default: Optional[str] = None) -> str:\n\"\"\"Get the property with that name or return empty string.\"\"\"\n    for prop in as_list(item.props):\n        if prop.name.strip().lower() == prop_name.strip().lower():\n            return prop.value.strip()\n    return default if default else ''\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rule_list_for_imp_req","title":"get_rule_list_for_imp_req(imp_req) staticmethod","text":"

                                                                            Get the list of rules applying to an imp_req as two lists.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_rule_list_for_imp_req(\n    imp_req: ossp.ImplementedRequirement\n) -> Tuple[List[str], List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to an imp_req as two lists.\"\"\"\n    comp_rules, rule_props = ControlInterface.get_rule_list_for_item(imp_req)\n    statement_rules = set()\n    for statement in as_list(imp_req.statements):\n        stat_rules, statement_props = ControlInterface.get_rule_list_for_item(statement)\n        statement_rules.update(stat_rules)\n        rule_props.extend(statement_props)\n    return comp_rules, sorted(statement_rules), rule_props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rule_list_for_item","title":"get_rule_list_for_item(item) staticmethod","text":"

                                                                            Get the list of rules applying to this item from its top level props.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_rule_list_for_item(item: TypeWithProps) -> Tuple[List[str], List[common.Property]]:\n\"\"\"Get the list of rules applying to this item from its top level props.\"\"\"\n    props = []\n    rule_list = []\n    for prop in as_list(item.props):\n        if prop.name == const.RULE_ID:\n            rule_list.append(prop.value)\n            props.append(prop)\n    return rule_list, props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rules_and_params_dict_from_item","title":"get_rules_and_params_dict_from_item(item) staticmethod","text":"

                                                                            Get the rule dict and params dict from item with props.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_rules_and_params_dict_from_item(\n    item: TypeWithProps\n) -> Tuple[Dict[str, Dict[str, str]], Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get the rule dict and params dict from item with props.\"\"\"\n    rules_dict, rules_props = ControlInterface.get_rules_dict_from_item(item)\n    params_dict, params_props = ControlInterface.get_params_dict_from_item(item)\n    rules_props.extend(params_props)\n    return rules_dict, params_dict, rules_props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_rules_dict_from_item","title":"get_rules_dict_from_item(item) staticmethod","text":"

                                                                            Get all rules found in this items props.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_rules_dict_from_item(item: TypeWithProps) -> Tuple[Dict[str, Dict[str, str]], List[common.Property]]:\n\"\"\"Get all rules found in this items props.\"\"\"\n    # rules is dict containing rule_id and description\n    rules_dict = {}\n    name = ''\n    desc = ''\n    id_ = ''\n    rules_props = []\n    for prop in as_list(item.props):\n        if prop.name == const.RULE_ID:\n            name = prop.value\n            id_ = prop.remarks\n            rules_props.append(prop)\n        elif prop.name == const.RULE_DESCRIPTION:\n            desc = prop.value\n            rules_props.append(prop)\n        # grab each pair in case there are multiple pairs\n        # then clear and look for new pair\n        if name and desc:\n            rules_dict[id_] = {'name': name, 'description': desc}\n            name = desc = id_ = ''\n    return rules_dict, rules_props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_section","title":"get_section(control, skip_section_list) staticmethod","text":"

                                                                            Get sections that are not in the list.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_section(control: cat.Control, skip_section_list: List[str]) -> Tuple[str, str, str, str]:\n\"\"\"Get sections that are not in the list.\"\"\"\n    id_, name, title = ControlInterface._find_section(control, skip_section_list)\n    if id_:\n        return id_, name, title, ControlInterface.get_control_section_prose(control, name)\n    return '', '', '', ''\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_set_params_from_item","title":"get_set_params_from_item(item) staticmethod","text":"

                                                                            Get set params that have values from control implementation or imp req.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_set_params_from_item(\n    item: Union[comp.ControlImplementation, comp.ImplementedRequirement]\n) -> Dict[str, comp.SetParameter]:\n\"\"\"Get set params that have values from control implementation or imp req.\"\"\"\n    return {\n        set_param.param_id: set_param\n        for set_param in as_filtered_list(item.set_parameters, lambda i: i.values)\n    }\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_sort_id","title":"get_sort_id(control, allow_none=False) staticmethod","text":"

                                                                            Get the sort-id for the control.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_sort_id(control: cat.Control, allow_none=False) -> Optional[str]:\n\"\"\"Get the sort-id for the control.\"\"\"\n    for prop in as_list(control.props):\n        if prop.name == const.SORT_ID:\n            return prop.value.strip()\n    return None if allow_none else control.id\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_statement_id","title":"get_statement_id(control) staticmethod","text":"

                                                                            Find the statement id in the control.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_statement_id(control: cat.Control) -> str:\n\"\"\"Find the statement id in the control.\"\"\"\n    for part in as_list(control.parts):\n        if part.name == const.STATEMENT:\n            return part.id\n    return ControlInterface.create_statement_id(control.id)\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.get_status_from_props","title":"get_status_from_props(item) staticmethod","text":"

                                                                            Get the status of an item from its props.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef get_status_from_props(item: TypeWithProps) -> common.ImplementationStatus:\n\"\"\"Get the status of an item from its props.\"\"\"\n    status = common.ImplementationStatus(state=const.STATUS_PLANNED)\n    for prop in as_list(item.props):\n        if prop.name == const.IMPLEMENTATION_STATUS:\n            status = ControlInterface._prop_as_status(prop)\n            break\n    return status\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.insert_imp_req_into_component","title":"insert_imp_req_into_component(component, new_imp_req, profile_title, trestle_root) staticmethod","text":"

                                                                            Insert imp req into component by matching source title and control id to existing imp req.

                                                                            Parameters:

                                                                            Name Type Description Default component comp.DefinedComponent

                                                                            The defined component receiving the imp_req

                                                                            required new_imp_req comp.ImplementedRequirement

                                                                            The new imp_req being added

                                                                            required profile_title str

                                                                            The title of the source profile for the control implementation containing the imp_req

                                                                            required

                                                                            Notes

                                                                            Inserts the imp_req on the first match found. Note it is possible two control implementations could have the same source and specify the same control

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef insert_imp_req_into_component(\n    component: comp.DefinedComponent,\n    new_imp_req: comp.ImplementedRequirement,\n    profile_title: str,\n    trestle_root: pathlib.Path\n) -> None:\n\"\"\"\n    Insert imp req into component by matching source title and control id to existing imp req.\n\n    Args:\n        component: The defined component receiving the imp_req\n        new_imp_req: The new imp_req being added\n        profile_title: The title of the source profile for the control implementation containing the imp_req\n\n    Notes:\n        Inserts the imp_req on the first match found.  Note it is possible two control implementations could\n        have the same source and specify the same control\n    \"\"\"\n    for control_imp in as_list(component.control_implementations):\n        _, control_imp_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(control_imp)\n        control_imp_rule_param_ids = [\n            param['name'] for params in control_imp_param_dict.values() for param in params\n        ]\n        if profile_title != ModelUtils.get_title_from_model_uri(trestle_root, control_imp.source):\n            continue\n        for imp_req in as_list(control_imp.implemented_requirements):\n            if imp_req.control_id != new_imp_req.control_id:\n                continue\n            _, imp_req_param_dict, _ = ControlInterface.get_rules_and_params_dict_from_item(imp_req)\n            imp_req_rule_param_ids = [param['name'] for params in imp_req_param_dict.values() for param in params]\n            status = ControlInterface.get_status_from_props(new_imp_req)\n            ControlInterface.insert_status_in_props(imp_req, status)\n            imp_req.description = new_imp_req.description\n            statement_dict = {stat.statement_id: stat for stat in as_list(imp_req.statements)}\n            # update set parameter values with values from markdown - but only for rule param vals\n            for set_param in as_list(new_imp_req.set_parameters):\n                if set_param.param_id not in (control_imp_rule_param_ids + imp_req_rule_param_ids):\n                    continue\n                found = False\n                for dest_param in as_list(imp_req.set_parameters):\n                    if dest_param.param_id != set_param.param_id:\n                        continue\n                    dest_param.values = set_param.values\n                    found = True\n                    break\n                # if rule parameter val was not already set by a set_param, make new set_param for it\n                if found:\n                    continue\n                # but first check if the parameter was already set with the same value in the control_imp\n                # if so we don't need to insert a new set_param in imp_req\n                for dest_param in as_list(control_imp.set_parameters):\n                    if dest_param.param_id != set_param.param_id:\n                        continue\n                    if dest_param.values == set_param.values:\n                        found = True\n                        break\n                if found:\n                    continue\n                imp_req.set_parameters = as_list(imp_req.set_parameters)\n                imp_req.set_parameters.append(\n                    comp.SetParameter(param_id=set_param.param_id, values=set_param.values)\n                )\n            new_statements: List[comp.Statement] = []\n            for statement in as_list(new_imp_req.statements):\n                # get the original version of the statement if available, or use new one\n                stat = statement_dict.get(statement.statement_id, statement)\n                # update the description and status from markdown\n                stat.description = statement.description\n                ControlInterface._copy_status_in_props(stat, statement)\n                new_statements.append(stat)\n            imp_req.statements = none_if_empty(new_statements)\n            return\n    logger.warning(\n        f'Unable to add imp req for component {component.title} control {new_imp_req.control_id} and source: {profile_title}'  # noqa E501\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.insert_status_in_props","title":"insert_status_in_props(item, status) staticmethod","text":"

                                                                            Insert status content into props of the item.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef insert_status_in_props(item: TypeWithProps, status: common.ImplementationStatus) -> None:\n\"\"\"Insert status content into props of the item.\"\"\"\n    prop = ControlInterface._status_as_prop(status)\n    ControlInterface._replace_prop(item, prop)\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.is_withdrawn","title":"is_withdrawn(control) staticmethod","text":"

                                                                            Determine if control is marked Withdrawn.

                                                                            Parameters:

                                                                            Name Type Description Default control cat.Control

                                                                            The control that may be marked withdrawn.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            True if marked withdrawn, false otherwise.

                                                                            This is determined by property with name 'status' with value 'Withdrawn'.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef is_withdrawn(control: cat.Control) -> bool:\n\"\"\"\n    Determine if control is marked Withdrawn.\n\n    Args:\n        control: The control that may be marked withdrawn.\n\n    Returns:\n        True if marked withdrawn, false otherwise.\n\n    This is determined by property with name 'status' with value 'Withdrawn'.\n    \"\"\"\n    for _ in as_filtered_list(\n            control.props,\n            lambda p: strip_lower_equals(p.name, 'status') and strip_lower_equals(p.value, 'withdrawn')):\n        return True\n    return False\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.item_has_rules","title":"item_has_rules(item) staticmethod","text":"

                                                                            Determine if the item has rules in its props.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef item_has_rules(item: TypeWithProps) -> bool:\n\"\"\"Determine if the item has rules in its props.\"\"\"\n    _, rules_props = ControlInterface.get_rules_dict_from_item(item)\n    return bool(rules_props)\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_dicts_deep","title":"merge_dicts_deep(dest, src, overwrite_header_values, depth=0, level=0) staticmethod","text":"

                                                                            Merge dict src into dest.

                                                                            New items are always added from src to dest. Items present in both will be overriden dest if overwrite_header_values is True.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef merge_dicts_deep(\n    dest: Dict[Any, Any],\n    src: Dict[Any, Any],\n    overwrite_header_values: bool,\n    depth: int = 0,\n    level: int = 0\n) -> None:\n\"\"\"\n    Merge dict src into dest.\n\n    New items are always added from src to dest.\n    Items present in both will be overriden dest if overwrite_header_values is True.\n    \"\"\"\n    for key in src.keys():\n        if key in dest:\n            if depth and level == depth:\n                if overwrite_header_values:\n                    dest[key] = src[key]\n                continue\n            # if they are both dicts, recurse\n            if isinstance(dest[key], dict) and isinstance(src[key], dict):\n                ControlInterface.merge_dicts_deep(dest[key], src[key], overwrite_header_values, depth, level + 1)\n            # if they are both lists, add any item that is not already in the list\n            elif isinstance(dest[key], list) and isinstance(src[key], list):\n                for item in src[key]:\n                    if item not in dest[key]:\n                        dest[key].append(item)\n            # otherwise override dest if needed\n            elif overwrite_header_values:\n                dest[key] = src[key]\n        else:\n            # if the item was not already in dest, add it from src\n            dest[key] = src[key]\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_part","title":"merge_part(dest, src) staticmethod","text":"

                                                                            Merge a source part into the destination part.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef merge_part(dest: common.Part, src: common.Part) -> common.Part:\n\"\"\"Merge a source part into the destination part.\"\"\"\n    dest.name = src.name if src.name else dest.name\n    dest.ns = src.ns if src.ns else dest.ns\n    dest.props = none_if_empty(ControlInterface.merge_props(dest.props, src.props))\n    dest.prose = src.prose\n    dest.title = src.title if src.title else dest.title\n    ControlInterface.merge_parts(dest, src)\n    return dest\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_parts","title":"merge_parts(dest, src) staticmethod","text":"

                                                                            Merge the parts from the source into the destination.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef merge_parts(dest: TypeWithParts, src: TypeWithParts) -> None:\n\"\"\"Merge the parts from the source into the destination.\"\"\"\n    if not dest.parts:\n        dest.parts = src.parts\n    elif not src.parts:\n        dest.parts = None\n    else:\n        new_parts: List[common.Part] = []\n        dest_map = {part.id: part for part in dest.parts}\n        for src_part in src.parts:\n            dest_part = dest_map.get(src_part.id, None)\n            if not dest_part:\n                new_parts.append(src_part)\n            else:\n                new_part = ControlInterface.merge_part(dest_part, src_part)\n                if new_part:\n                    new_parts.append(new_part)\n        dest.parts = new_parts\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.merge_props","title":"merge_props(dest, src) staticmethod","text":"

                                                                            Merge a source list of properties into a destination list.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef merge_props(dest: Optional[List[common.Property]],\n                src: Optional[List[common.Property]]) -> List[common.Property]:\n\"\"\"Merge a source list of properties into a destination list.\"\"\"\n    if not src:\n        return dest\n    new_props: List[common.Property] = []\n    src_map = {prop.name: prop for prop in src}\n    dest_map = {prop.name: prop for prop in dest}\n    all_names = set(src_map.keys()).union(dest_map.keys())\n    for name in sorted(all_names):\n        if name in src_map and name not in dest_map:\n            new_props.append(src_map[name])\n        elif name in dest_map and name not in src_map:\n            new_props.append(dest_map[name])\n        else:\n            new_prop = dest_map[name]\n            src_prop = src_map[name]\n            new_prop.class_ = src_prop.class_ if src_prop.class_ else new_prop.class_\n            new_prop.ns = src_prop.ns if src_prop.ns else new_prop.ns\n            new_prop.remarks = src_prop.remarks if src_prop.remarks else new_prop.remarks\n            new_prop.uuid = src_prop.uuid if src_prop.uuid else new_prop.uuid\n            new_prop.value = src_prop.value\n            new_props.append(new_prop)\n    return new_props\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.param_to_str","title":"param_to_str(param, param_rep, verbose=False, brackets=False, params_format=None, value_assigned_prefix=None, value_not_assigned_prefix=None, param_dict=None) staticmethod","text":"

                                                                            Convert parameter to string based on best available representation.

                                                                            Parameters:

                                                                            Name Type Description Default param common.Parameter

                                                                            the parameter to convert

                                                                            required param_rep ParameterRep

                                                                            how to represent the parameter

                                                                            required verbose bool

                                                                            provide verbose text for selection choices

                                                                            False brackets bool

                                                                            add brackets around the lists of items

                                                                            False params_format Optional[str]

                                                                            a string containing a single dot that represents a form of highlighting around the param

                                                                            None value_assigned_prefix Optional[str]

                                                                            string to place before the parameter string if a value was assigned

                                                                            None value_not_assigned_prefix Optional[str]

                                                                            string to place before the parameter string if value not assigned

                                                                            None

                                                                            Returns:

                                                                            Type Description Optional[str]

                                                                            formatted string or None

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef param_to_str(\n    param: common.Parameter,\n    param_rep: ParameterRep,\n    verbose: bool = False,\n    brackets: bool = False,\n    params_format: Optional[str] = None,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None,\n    param_dict: Dict[str, common.Parameter] = None\n) -> Optional[str]:\n\"\"\"\n    Convert parameter to string based on best available representation.\n\n    Args:\n        param: the parameter to convert\n        param_rep: how to represent the parameter\n        verbose: provide verbose text for selection choices\n        brackets: add brackets around the lists of items\n        params_format: a string containing a single dot that represents a form of highlighting around the param\n        value_assigned_prefix: string to place before the parameter string if a value was assigned\n        value_not_assigned_prefix: string to place before the parameter string if value not assigned\n\n    Returns:\n        formatted string or None\n    \"\"\"\n    param_str = None\n    if param_rep == ParameterRep.VALUE_OR_STRING_NONE:\n        param_str = ControlInterface._param_values_as_str(param)\n        param_str = param_str if param_str else 'None'\n    elif param_rep == ParameterRep.LABEL_OR_CHOICES:\n        param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n    elif param_rep == ParameterRep.VALUE_OR_LABEL_OR_CHOICES:\n        param_str = ControlInterface._param_values_as_str(param)\n        if not param_str:\n            param_str = ControlInterface._param_label_choices_as_str(param, verbose, brackets)\n    elif param_rep == ParameterRep.VALUE_OR_EMPTY_STRING:\n        param_str = ControlInterface._param_values_as_str(param, brackets)\n        if not param_str:\n            param_str = ''\n    elif param_rep == ParameterRep.ASSIGNMENT_FORM:\n        param_str = ControlInterface._param_values_assignment_str(\n            param, param_dict, value_assigned_prefix, value_not_assigned_prefix\n        )\n        if not param_str:\n            param_str = ''\n    elif param_rep == ParameterRep.LABEL_FORM:\n        param_str = ControlInterface._param_labels_assignment_str(param, value_not_assigned_prefix)\n        if not param_str:\n            param_str = ''\n    return ControlInterface._apply_params_format(param_str, params_format)\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.replace_control_prose","title":"replace_control_prose(control, param_dict, params_format=None, param_rep=<ParameterRep.VALUE_OR_LABEL_OR_CHOICES: 3>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                                                            Replace the control prose according to set_param.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef replace_control_prose(\n    control: cat.Control,\n    param_dict: Dict[str, common.Parameter],\n    params_format: Optional[str] = None,\n    param_rep: ParameterRep = ParameterRep.VALUE_OR_LABEL_OR_CHOICES,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> None:\n\"\"\"Replace the control prose according to set_param.\"\"\"\n    # first replace all choices that reference parameters\n    # note that in ASSIGNMENT_FORM each choice with a parameter will end up as [Assignment: value]\n    for param in as_list(control.params):\n        ControlInterface._replace_param_choices(\n            param,\n            param_dict,\n            params_format,\n            param_rep,\n            show_value_warnings,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n    for part in as_list(control.parts):\n        if part.prose is not None:\n            fixed_prose = ControlInterface._replace_params(\n                part.prose,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n            # change the prose in the control itself\n            part.prose = fixed_prose\n        for prt in as_list(part.parts):\n            ControlInterface._replace_part_prose(\n                control,\n                prt,\n                param_dict,\n                params_format,\n                param_rep,\n                show_value_warnings,\n                value_assigned_prefix,\n                value_not_assigned_prefix\n            )\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.setparam_to_param","title":"setparam_to_param(param_id, set_param) staticmethod","text":"

                                                                            Convert setparameter to parameter.

                                                                            Parameters:

                                                                            Name Type Description Default param_id str

                                                                            the id of the parameter

                                                                            required set_param prof.SetParameter

                                                                            the set_parameter from a profile

                                                                            required

                                                                            Returns:

                                                                            Type Description common.Parameter

                                                                            a Parameter with param_id and content from the SetParameter

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef setparam_to_param(param_id: str, set_param: prof.SetParameter) -> common.Parameter:\n\"\"\"\n    Convert setparameter to parameter.\n\n    Args:\n        param_id: the id of the parameter\n        set_param: the set_parameter from a profile\n\n    Returns:\n        a Parameter with param_id and content from the SetParameter\n    \"\"\"\n    return common.Parameter(\n        id=param_id, values=set_param.values, select=set_param.select, label=set_param.label, props=set_param.props\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.strip_to_make_ncname","title":"strip_to_make_ncname(label) staticmethod","text":"

                                                                            Strip chars to conform with NCNAME regex.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef strip_to_make_ncname(label: str) -> str:\n\"\"\"Strip chars to conform with NCNAME regex.\"\"\"\n    orig_label = label\n    # make sure first char is allowed\n    while label and label[0] not in const.NCNAME_UTF8_FIRST_CHAR_OPTIONS:\n        label = label[1:]\n    new_label = label[:1]\n    # now check remaining chars\n    if len(label) > 1:\n        for ii in range(1, len(label)):\n            if label[ii] in const.NCNAME_UTF8_OTHER_CHAR_OPTIONS:\n                new_label += label[ii]\n    # do final check to confirm it is NCNAME\n    match = re.search(const.NCNAME_REGEX, new_label)\n    if not match:\n        raise TrestleError(f'Unable to convert label {orig_label} to NCNAME format.')\n    return new_label\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ControlInterface.uniquify_set_params","title":"uniquify_set_params(set_params) staticmethod","text":"

                                                                            Remove items with same param_id with priority to later items.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @staticmethod\ndef uniquify_set_params(set_params: Optional[List[TypeWithParamId]]) -> List[TypeWithParamId]:\n\"\"\"Remove items with same param_id with priority to later items.\"\"\"\n    found_ids: Set[str] = set()\n    unique_list: List[TypeWithParamId] = []\n    for set_param in reversed(as_list(set_params)):\n        if set_param.param_id not in found_ids:\n            unique_list.append(set_param)\n            found_ids.add(set_param.param_id)\n    return list(reversed(unique_list))\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep","title":" ParameterRep (Enum) ","text":"

                                                                            Enum for ways to represent a parameter.

                                                                            Source code in trestle/core/control_interface.py
                                                                            class ParameterRep(Enum):\n\"\"\"Enum for ways to represent a parameter.\"\"\"\n\n    LEAVE_MOUSTACHE = 0\n    VALUE_OR_STRING_NONE = 1\n    LABEL_OR_CHOICES = 2\n    VALUE_OR_LABEL_OR_CHOICES = 3\n    VALUE_OR_EMPTY_STRING = 4\n    ASSIGNMENT_FORM = 5\n    LABEL_FORM = 6\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.ASSIGNMENT_FORM","title":"ASSIGNMENT_FORM","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.LABEL_FORM","title":"LABEL_FORM","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.LABEL_OR_CHOICES","title":"LABEL_OR_CHOICES","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.LEAVE_MOUSTACHE","title":"LEAVE_MOUSTACHE","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.VALUE_OR_EMPTY_STRING","title":"VALUE_OR_EMPTY_STRING","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.VALUE_OR_LABEL_OR_CHOICES","title":"VALUE_OR_LABEL_OR_CHOICES","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.ParameterRep.VALUE_OR_STRING_NONE","title":"VALUE_OR_STRING_NONE","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo","title":" PartInfo dataclass","text":"

                                                                            Class to capture control part info needed in markdown.

                                                                            Source code in trestle/core/control_interface.py
                                                                            @dataclass\nclass PartInfo:\n\"\"\"Class to capture control part info needed in markdown.\"\"\"\n\n    name: str\n    prose: str\n    smt_part: str = ''\n    props: Optional[List[common.Property]] = None\n    parts: Optional[List[PartInfo]] = None\n\n    def to_dicts(self, part_id_map: Dict[str, str]) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:\n\"\"\"Convert the part info to a dict or list of props.\"\"\"\n        prop_list = []\n        part = {}\n        # if it has a part name then it is a part with prose\n        if self.name:\n            part['name'] = part_id_map.get(self.name, self.name)\n            if self.prose:\n                part['prose'] = self.prose\n            if self.parts:\n                all_subparts = []\n                for subpart in self.parts:\n                    subpart_dict, _ = subpart.to_dicts(part_id_map)\n                    all_subparts.append(subpart_dict)\n                part['parts'] = all_subparts\n\n        # otherwise it is a list of props\n        else:\n            for prop in as_list(self.props):\n                prop_d = {'name': prop.name, 'value': prop.value}\n                if prop.ns:\n                    prop_d['ns'] = str(prop.ns)\n                if self.smt_part:\n                    prop_d['smt-part'] = part_id_map.get(self.smt_part, self.smt_part)\n                prop_list.append(prop_d)\n        return part, prop_list\n
                                                                            "},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.name","title":"name: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.parts","title":"parts: Optional[List[trestle.core.control_interface.PartInfo]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.props","title":"props: Optional[List[trestle.oscal.common.Property]] dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.prose","title":"prose: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.smt_part","title":"smt_part: str dataclass-field","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.__init__","title":"__init__(self, name, prose, smt_part='', props=None, parts=None) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.control_interface/#trestle.core.control_interface.PartInfo.to_dicts","title":"to_dicts(self, part_id_map)","text":"

                                                                            Convert the part info to a dict or list of props.

                                                                            Source code in trestle/core/control_interface.py
                                                                            def to_dicts(self, part_id_map: Dict[str, str]) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:\n\"\"\"Convert the part info to a dict or list of props.\"\"\"\n    prop_list = []\n    part = {}\n    # if it has a part name then it is a part with prose\n    if self.name:\n        part['name'] = part_id_map.get(self.name, self.name)\n        if self.prose:\n            part['prose'] = self.prose\n        if self.parts:\n            all_subparts = []\n            for subpart in self.parts:\n                subpart_dict, _ = subpart.to_dicts(part_id_map)\n                all_subparts.append(subpart_dict)\n            part['parts'] = all_subparts\n\n    # otherwise it is a list of props\n    else:\n        for prop in as_list(self.props):\n            prop_d = {'name': prop.name, 'value': prop.value}\n            if prop.ns:\n                prop_d['ns'] = str(prop.ns)\n            if self.smt_part:\n                prop_d['smt-part'] = part_id_map.get(self.smt_part, self.smt_part)\n            prop_list.append(prop_d)\n    return part, prop_list\n
                                                                            "},{"location":"api_reference/trestle.core.control_reader/","title":"control_reader","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader","title":"trestle.core.control_reader","text":"

                                                                            Handle reading of writing controls from markdown.

                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader","title":" ControlReader ","text":"

                                                                            Class to read controls from markdown.

                                                                            Source code in trestle/core/control_reader.py
                                                                            class ControlReader:\n\"\"\"Class to read controls from markdown.\"\"\"\n\n    @staticmethod\n    def _clean_prose(prose: List[str]) -> List[str]:\n        # remove empty and horizontal rule lines at start and end of list of prose lines\n        forward_index = 0\n        for line in prose:\n            if line.strip() and not line.startswith('____'):\n                break\n            forward_index += 1\n        new_prose = prose[forward_index:]\n        reverse_index = 0\n        for line in reversed(new_prose):\n            if line.strip() and not line.startswith('____'):\n                break\n            reverse_index += 1\n        clean_prose = new_prose[:len(new_prose) - reverse_index]\n        clean_prose = clean_prose if clean_prose else ['']\n        # if there is no useful prose this will return [''] and allow generation of a statement with empty prose\n        return clean_prose\n\n    @staticmethod\n    def _comp_name_in_dict(comp_name: str, comp_dict: CompDict) -> str:\n\"\"\"If the name is already in the dict in a similar form, stick to that form.\"\"\"\n        simple_name = ControlReader.simplify_name(comp_name)\n        for name in comp_dict.keys():\n            if simple_name == ControlReader.simplify_name(name):\n                return name\n        return comp_name\n\n    @staticmethod\n    def _add_node_to_dict(\n        comp_name: Optional[str],\n        label: str,\n        comp_dict: CompDict,\n        node: ControlMarkdownNode,\n        control_id: str,\n        comp_list: List[str],\n        context: ControlContext\n    ) -> None:\n\"\"\"\n        Extract the label, prose, possible component name - along with implementation status.\n\n        In component mode there is only one component and its name is not in markdown.\n        In ssp mode there are many components in each md file.\n        \"\"\"\n        component_mode = context.purpose == ContextPurpose.COMPONENT\n        # for ssp, ### marks component name but for component it is ##\n        # if it is a header, make sure it has correct format\n        if node.key and node.key[0] == '#' and ControlInterface.bad_header(node.key):\n            raise TrestleError(f'Improper header format for control {control_id}: {node.key}')\n        if not component_mode:\n            # look for component name heading if present\n            prefix = '### '\n            if node.key.startswith(prefix):\n                if len(node.key.split()) <= 1:\n                    raise TrestleError(\n                        f'Header line in control {control_id} markdown starts with {prefix} but has no content.'\n                    )\n                comp_name = node.key.split(' ', 1)[1].strip()\n                simp_comp_name = ControlReader.simplify_name(comp_name)\n                if simp_comp_name in comp_list:\n                    raise TrestleError(\n                        f'Control {control_id} has a section with two component headings for {comp_name}.  '\n                        'Please combine the sections so there is only one heading for each component in a '\n                        'statement.'\n                    )\n                comp_list.append(simp_comp_name)\n                comp_name = ControlReader._comp_name_in_dict(comp_name, comp_dict)\n\n        # prose may be empty in md and we want to capture that so put it in the comp_dict\n        prose = '\\n'.join(ControlReader._clean_prose(node.content.text))\n        # add the prose to the comp_dict, creating new entry as needed\n        if comp_name in comp_dict:\n            if label in comp_dict[comp_name]:\n                comp_dict[comp_name][label].prose = prose\n            else:\n                # create new entry with prose\n                comp_dict[comp_name][label] = ComponentImpInfo(prose=prose, rules=[], props=[])\n        elif comp_name:\n            comp_dict[comp_name] = {label: ComponentImpInfo(prose=prose, rules=[], props=[])}\n\n        # build list of subnodes that get handled specially so they aren't processed here\n        subnode_kill: List[int] = []\n        status_str = None\n        remarks_str = None\n        rules_list: List[str] = []\n        for ii, subnode in enumerate(node.subnodes):\n            if subnode.key.find(const.IMPLEMENTATION_STATUS_REMARKS_HEADER) >= 0:\n                remarks_str = subnode.key.split(maxsplit=4)[-1]\n                subnode_kill.append(ii)\n            elif subnode.key.find(const.IMPLEMENTATION_STATUS_HEADER) >= 0:\n                status_str = subnode.key.split(maxsplit=3)[-1]\n                subnode_kill.append(ii)\n            elif subnode.key.find('Rules:') >= 0:\n                rules_list = [text[2:] for text in subnode.content.text if text.startswith('- ')]\n                subnode_kill.append(ii)\n        if status_str:\n            new_status = common.ImplementationStatus(state=status_str, remarks=remarks_str)\n            if comp_name not in comp_dict:\n                comp_dict[comp_name] = {}\n            if label not in comp_dict[comp_name]:\n                comp_dict[comp_name][label] = ComponentImpInfo(prose='', rules=[], props=[])\n            comp_dict[comp_name][label].status = new_status\n        if rules_list:\n            comp_dict[comp_name][label].rules = rules_list\n        delete_list_from_list(node.subnodes, subnode_kill)\n        for subnode in as_list(node.subnodes):\n            ControlReader._add_node_to_dict(comp_name, label, comp_dict, subnode, control_id, comp_list, context)\n\n    @staticmethod\n    def _insert_header_content(\n        imp_req: generic.GenericImplementedRequirement, header: Dict[str, Any], control_id: str\n    ) -> None:\n\"\"\"Insert yaml header content into the imp_req and its by_comps as props.\"\"\"\n        dict_ = header.get(const.TRESTLE_PROPS_TAG, {})\n        roles = as_list(dict_.get(const.RESPONSIBLE_ROLES, []))\n        props = []\n        responsible_roles = []\n        for role in roles:\n            if isinstance(role, str):\n                # role_id must conform to NCNAME regex\n                role = role.strip().replace(' ', '_')\n                if role:\n                    responsible_roles.append(common.ResponsibleRole(role_id=role))\n            else:\n                logger.warning(f'Role in header for control {control_id} not recognized: {role}')\n        if props:\n            imp_req.props = as_list(imp_req.props)\n            imp_req.props.extend(props)\n        if responsible_roles:\n            imp_req.responsible_roles = as_list(imp_req.responsible_roles)\n            imp_req.responsible_roles.extend(responsible_roles)\n            imp_req.responsible_roles = none_if_empty(imp_req.responsible_roles)\n            # enforce single list of resp. roles for control and each by_comp\n            for by_comp in as_list(imp_req.by_components):\n                by_comp.responsible_roles = imp_req.responsible_roles\n\n    @staticmethod\n    def simplify_name(name: str) -> str:\n\"\"\"Simplify the name to ignore variations in case, space, hyphen, underscore, slash.\"\"\"\n        return name.lower().replace(' ', '').replace('-', '').replace('_', '').replace('/', '')\n\n    @staticmethod\n    def _get_label_from_implementation_header(imp_header: str):\n        # assumed to be of form: Implementation for part a.\n        split_header = imp_header.split(' ', 4)\n        if len(split_header) != 5:\n            raise TrestleError(f'Implementation header cannot be parsed for statement part: {imp_header}')\n        return split_header[4].strip()\n\n    @staticmethod\n    def read_control_info_from_md(control_file: pathlib.Path,\n                                  context: ControlContext) -> Tuple[Dict[str, List[str]], CompDict]:\n\"\"\"\n        Find all labels and associated implementation prose in the markdown for this control.\n\n        Args:\n            control_file: path to the control markdown file\n            context: context of the control usage\n\n        Returns:\n            The yaml header as dict in second part of tuple.\n            Adds to the passed in comp_dict.\n        \"\"\"\n        yaml_header = {}\n        comp_dict = {}\n\n        if not control_file.exists():\n            return yaml_header, comp_dict\n        # if the file exists, load the contents but do not use prose from comp_dict\n        # for non ssp or component mode just use empty string for comp\n        comp_name = ''\n        try:\n            control_id = control_file.stem\n            if context.purpose == ContextPurpose.COMPONENT:\n                comp_name = context.comp_name if context.comp_name else const.SSP_MAIN_COMP_NAME\n\n            md_api = MarkdownAPI()\n            yaml_header, control_md = md_api.processor.process_markdown(control_file)\n\n            # first get the header strings, including statement labels, for statement imp reqs\n            imp_string = '## Implementation '\n            headers = control_md.get_all_headers_for_level(2)\n            # get e.g. ## Implementation a.  ## Implementation b. etc\n            imp_header_list = [header for header in headers if header.startswith(imp_string)]\n\n            # now get the (one) header for the main solution\n            main_headers = list(control_md.get_all_headers_for_key(const.SSP_MD_IMPLEMENTATION_QUESTION, False))\n            # should be only one header, so warn if others found\n            if main_headers:\n                if len(main_headers) > 1:\n                    logger.warning(\n                        f'Control {control_id} has {len(main_headers)} main header responses.  Will use first one only.'\n                    )\n                main_header = main_headers[0]\n                node = control_md.get_all_nodes_for_keys([main_header], False)[0]\n                # this node is top level so it will have empty label\n                # it may have subnodes of Rules, Implementation Status, Implementaton Remarks\n                ControlReader._add_node_to_dict(comp_name, '', comp_dict, node, control_id, [], context)\n            for imp_header in imp_header_list:\n                label = ControlReader._get_label_from_implementation_header(imp_header)\n                node = control_md.get_node_for_key(imp_header)\n                ControlReader._add_node_to_dict(comp_name, label, comp_dict, node, control_id, [], context)\n\n        except TrestleError as e:\n            raise TrestleError(f'Error occurred reading {control_file}: {e}')\n        return yaml_header, comp_dict\n\n    @staticmethod\n    def _handle_empty_prose(prose: str, id_: str) -> str:\n\"\"\"Regard prompt text or id_ as no prose and return blank string.\"\"\"\n        if prose.startswith(const.SSP_ADD_IMPLEMENTATION_PREFIX) or prose == id_:\n            return ''\n        return prose\n\n    @staticmethod\n    def read_implemented_requirement(control_file: pathlib.Path,\n                                     context: ControlContext) -> Tuple[str, comp.ImplementedRequirement]:\n\"\"\"\n        Get the implementated requirement associated with given control and link to existing components or new ones.\n\n        Args:\n            control_file: path of the control markdown file\n            context: context of the control usage\n\n        Returns:\n            Tuple: The control sort-id and the one implemented requirement for this control.\n\n        Notes:\n            Each statement may have several responses, with each response in a by_component for a specific component.\n            statement_map keeps track of statements that may have several by_component responses.\n            This is only used during component assemble and only for updating one component.\n        \"\"\"\n        control_id = control_file.stem\n        md_header, md_comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n        comp_name = context.component.title\n\n        statement_map: Dict[str, comp.Statement] = {}\n        # create a new implemented requirement linked to the control id to hold the statements\n        imp_req = gens.generate_sample_model(comp.ImplementedRequirement)\n        imp_req.control_id = control_id\n\n        imp_req.statements = []\n        comp_dict = md_comp_dict[comp_name]\n        for label, comp_info in comp_dict.items():\n            # only assemble responses with associated rules\n            if not comp_info.rules:\n                continue\n            # if no label it applies to the imp_req itself rather than a statement\n            if not label:\n                imp_req.description = ControlReader._handle_empty_prose(comp_info.prose, control_id)\n                ControlInterface.insert_status_in_props(imp_req, comp_info.status)\n                continue\n            statement_id = ControlInterface.create_statement_id(control_id)\n            if label in ['', const.STATEMENT]:\n                statement_part_id = statement_id\n            else:\n                clean_label = label.strip('.')\n                statement_part_id = ControlInterface.strip_to_make_ncname(f'{statement_id}.{clean_label}')\n            if statement_part_id in statement_map:\n                statement = statement_map[statement_part_id]\n            else:\n                statement = gens.generate_sample_model(comp.Statement)\n                statement.statement_id = statement_part_id\n                statement_map[statement_part_id] = statement\n            statement.description = comp_info.prose\n            statement.props = none_if_empty(ControlInterface.clean_props(comp_info.props))\n            ControlInterface.insert_status_in_props(statement, comp_info.status)\n\n        imp_req.statements = list(statement_map.values())\n        imp_req.set_parameters = []\n\n        for _, param_dict_list in md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {}).items():\n            for param_dict in param_dict_list:\n                values = param_dict.get(const.VALUES, [])\n                comp_values = param_dict.get(const.COMPONENT_VALUES, [])\n                values = comp_values if comp_values else values\n                set_param = ossp.SetParameter(param_id=param_dict['name'], values=values)\n                imp_req.set_parameters.append(set_param)\n        imp_req.statements = none_if_empty(list(statement_map.values()))\n        imp_req.set_parameters = none_if_empty(imp_req.set_parameters)\n\n        ControlReader._insert_header_content(imp_req, md_header, control_id)\n        sort_id = md_header.get(const.SORT_ID, control_id)\n        return sort_id, imp_req\n\n    @staticmethod\n    def get_props_list(control_id: str, label_map: Dict[str, str],\n                       yaml_header: Dict[str, Any]) -> Tuple[List[common.Property], Dict[str, List[common.Property]]]:\n\"\"\"Get the list of props in the yaml header of this control as separate lists with and without by_id.\"\"\"\n        prop_list = yaml_header.get(const.TRESTLE_ADD_PROPS_TAG, [])\n        props = []\n        props_by_id = {}\n        for prop_d in prop_list:\n            by_id = prop_d.get('smt-part', None)\n            if by_id and control_id in label_map:\n                by_id = label_map[control_id].get(by_id, by_id)\n            prop = common.Property(name=prop_d['name'], value=prop_d['value'], ns=prop_d.get('ns', None))\n            if by_id:\n                if by_id not in props_by_id:\n                    props_by_id[by_id] = []\n                props_by_id[by_id].append(prop)\n            else:\n                props.append(prop)\n        return props, props_by_id\n\n    @staticmethod\n    def read_editable_content(\n        control_path: pathlib.Path,\n        required_sections_list: List[str],\n        part_label_to_id_map: Dict[str, Dict[str, str]],\n        cli_section_dict: Dict[str, str],\n        write_mode: bool\n    ) -> Tuple[str, List[prof.Alter], Dict[str, Any]]:\n\"\"\"Get parts for the markdown control corresponding to Editable Content - along with the set-parameter dict.\"\"\"\n        control_id = control_path.stem\n\n        md_api = MarkdownAPI()\n        yaml_header, control_tree = md_api.processor.process_control_markdown(control_path, cli_section_dict, part_label_to_id_map)  # noqa: E501\n        # extract the sort_id if present in header\n        sort_id = yaml_header.get(const.SORT_ID, control_id)\n\n        editable_node = None\n        for header in list(control_tree.get_all_headers_for_level(1)):\n            if header.startswith('# Editable'):\n                editable_node = control_tree.get_node_for_key(header)\n                break\n        if not editable_node:\n            return sort_id, [], {}\n\n        editable_parts = control_tree.get_editable_parts_and_subparts()\n        by_id_parts = control_tree.get_by_id_parts()\n        found_sections = [p.name for p in editable_parts]\n\n        # Validate that all required sections have a prose\n        for editable_part in editable_parts:\n            if not write_mode and editable_part.name in required_sections_list and editable_part.prose.startswith(\n                    const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT):\n                raise TrestleError(f'Control {control_id} is missing prose for required section {editable_part.title}')\n\n        # Validate that all required sections are present\n        missing_sections = set(required_sections_list) - set(found_sections)\n        if missing_sections:\n            raise TrestleError(f'Control {control_id} is missing required sections {missing_sections}')\n        param_dict: Dict[str, Any] = {}\n        # get set_params from the header and add to parm_dict\n        header_params = yaml_header.get(const.SET_PARAMS_TAG, {})\n        if header_params:\n            param_dict.update(header_params)\n\n        props, props_by_id = ControlReader.get_props_list(control_id, part_label_to_id_map, yaml_header)\n\n        # When adding props without by_id it can either be starting or ending and we default to ending\n        # This is the default behavior as described for implicit binding in\n        # https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/\n        # When adding props to a part using by_id, it is the same situation because it cannot be before or after since\n        # props are not in the same list as parts\n\n        adds: List[prof.Add] = []\n\n        # add the parts and props at control level\n        if editable_parts or props:\n            adds.append(\n                prof.Add(\n                    parts=none_if_empty(editable_parts),\n                    props=none_if_empty(props),\n                    position=prof.PositionValidValues.ending.value\n                )\n            )\n\n        # add the parts and props at the part level, by-id\n        by_ids = set(by_id_parts.keys()).union(props_by_id.keys())\n        for by_id in sorted(by_ids):\n            parts = by_id_parts.get(by_id, None)\n            props = props_by_id.get(by_id, None)\n            adds.append(prof.Add(parts=parts, props=props, position=prof.PositionValidValues.ending.value, by_id=by_id))\n\n        new_alters = []\n        if adds:\n            new_alters = [prof.Alter(control_id=control_id, adds=adds)]\n        return sort_id, new_alters, param_dict\n\n    @staticmethod\n    def _update_display_prop_namespace(item: TypeWithProps):\n\"\"\"Set namespace for special property display_name.\"\"\"\n        for prop in as_list(item.props):\n            if prop.name == const.DISPLAY_NAME:\n                prop.ns = const.TRESTLE_GENERIC_NS\n\n    @staticmethod\n    def read_control(control_path: pathlib.Path, set_parameters_flag: bool) -> Tuple[cat.Control, str]:\n\"\"\"Read the control and group title from the markdown file.\"\"\"\n        control = gens.generate_sample_model(cat.Control)\n        md_api = MarkdownAPI()\n        yaml_header, control_tree = md_api.processor.process_control_markdown(control_path)\n        control_titles = list(control_tree.get_all_headers_for_level(1))\n        if len(control_titles) == 0:\n            raise TrestleError(f'Control markdown: {control_path} contains no control title.')\n        if len(control_titles) > 1:\n            raise TrestleError(f'Control markdown: {control_path} contains multiple control titles {control_titles}.')\n\n        control.id = control_tree.subnodes[0].content.control_id\n        group_title = control_tree.subnodes[0].content.control_group\n        control.title = control_tree.subnodes[0].content.control_title\n\n        control_statement = control_tree.get_control_statement()\n        statement_part = control_statement.content.part\n\n        control.parts = [statement_part] if statement_part else None\n        control_objective = control_tree.get_control_objective()\n        if control_objective is not None:\n            objective_part = control_objective.content.part\n            if objective_part:\n                if control.parts:\n                    control.parts.append(objective_part)\n                else:\n                    control.parts = [objective_part]\n\n        control_guidance = control_tree.get_control_guidance()\n        if control_guidance is not None:\n            guidance_part = control_guidance.content.part\n            if guidance_part:\n                if control.parts:\n                    control.parts.append(guidance_part)\n                else:\n                    control.parts = [guidance_part]\n\n        all_other_parts = []\n        for section_node in control_tree.get_other_control_parts():\n            parts = section_node.content.part\n            all_other_parts.extend([parts])\n        if all_other_parts:\n            if control.parts:\n                control.parts.extend(all_other_parts)\n            else:\n                control.parts = all_other_parts\n\n        if set_parameters_flag:\n            params: Dict[str, str] = yaml_header.get(const.SET_PARAMS_TAG, [])\n            if params:\n                control.params = []\n                for id_, param_dict in params.items():\n                    param_dict['id'] = id_\n                    param = ModelUtils.dict_to_parameter(param_dict)\n                    # if display_name is in list of properties, set its namespace\n                    ControlReader._update_display_prop_namespace(param)\n                    control.params.append(param)\n        sort_id = deep_get(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], None)\n        if sort_id:\n            control.props = control.props if control.props else []\n            control.props.append(common.Property(name=const.SORT_ID, value=sort_id))\n        return control, group_title\n
                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.get_props_list","title":"get_props_list(control_id, label_map, yaml_header) staticmethod","text":"

                                                                            Get the list of props in the yaml header of this control as separate lists with and without by_id.

                                                                            Source code in trestle/core/control_reader.py
                                                                            @staticmethod\ndef get_props_list(control_id: str, label_map: Dict[str, str],\n                   yaml_header: Dict[str, Any]) -> Tuple[List[common.Property], Dict[str, List[common.Property]]]:\n\"\"\"Get the list of props in the yaml header of this control as separate lists with and without by_id.\"\"\"\n    prop_list = yaml_header.get(const.TRESTLE_ADD_PROPS_TAG, [])\n    props = []\n    props_by_id = {}\n    for prop_d in prop_list:\n        by_id = prop_d.get('smt-part', None)\n        if by_id and control_id in label_map:\n            by_id = label_map[control_id].get(by_id, by_id)\n        prop = common.Property(name=prop_d['name'], value=prop_d['value'], ns=prop_d.get('ns', None))\n        if by_id:\n            if by_id not in props_by_id:\n                props_by_id[by_id] = []\n            props_by_id[by_id].append(prop)\n        else:\n            props.append(prop)\n    return props, props_by_id\n
                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_control","title":"read_control(control_path, set_parameters_flag) staticmethod","text":"

                                                                            Read the control and group title from the markdown file.

                                                                            Source code in trestle/core/control_reader.py
                                                                            @staticmethod\ndef read_control(control_path: pathlib.Path, set_parameters_flag: bool) -> Tuple[cat.Control, str]:\n\"\"\"Read the control and group title from the markdown file.\"\"\"\n    control = gens.generate_sample_model(cat.Control)\n    md_api = MarkdownAPI()\n    yaml_header, control_tree = md_api.processor.process_control_markdown(control_path)\n    control_titles = list(control_tree.get_all_headers_for_level(1))\n    if len(control_titles) == 0:\n        raise TrestleError(f'Control markdown: {control_path} contains no control title.')\n    if len(control_titles) > 1:\n        raise TrestleError(f'Control markdown: {control_path} contains multiple control titles {control_titles}.')\n\n    control.id = control_tree.subnodes[0].content.control_id\n    group_title = control_tree.subnodes[0].content.control_group\n    control.title = control_tree.subnodes[0].content.control_title\n\n    control_statement = control_tree.get_control_statement()\n    statement_part = control_statement.content.part\n\n    control.parts = [statement_part] if statement_part else None\n    control_objective = control_tree.get_control_objective()\n    if control_objective is not None:\n        objective_part = control_objective.content.part\n        if objective_part:\n            if control.parts:\n                control.parts.append(objective_part)\n            else:\n                control.parts = [objective_part]\n\n    control_guidance = control_tree.get_control_guidance()\n    if control_guidance is not None:\n        guidance_part = control_guidance.content.part\n        if guidance_part:\n            if control.parts:\n                control.parts.append(guidance_part)\n            else:\n                control.parts = [guidance_part]\n\n    all_other_parts = []\n    for section_node in control_tree.get_other_control_parts():\n        parts = section_node.content.part\n        all_other_parts.extend([parts])\n    if all_other_parts:\n        if control.parts:\n            control.parts.extend(all_other_parts)\n        else:\n            control.parts = all_other_parts\n\n    if set_parameters_flag:\n        params: Dict[str, str] = yaml_header.get(const.SET_PARAMS_TAG, [])\n        if params:\n            control.params = []\n            for id_, param_dict in params.items():\n                param_dict['id'] = id_\n                param = ModelUtils.dict_to_parameter(param_dict)\n                # if display_name is in list of properties, set its namespace\n                ControlReader._update_display_prop_namespace(param)\n                control.params.append(param)\n    sort_id = deep_get(yaml_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], None)\n    if sort_id:\n        control.props = control.props if control.props else []\n        control.props.append(common.Property(name=const.SORT_ID, value=sort_id))\n    return control, group_title\n
                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_control_info_from_md","title":"read_control_info_from_md(control_file, context) staticmethod","text":"

                                                                            Find all labels and associated implementation prose in the markdown for this control.

                                                                            Parameters:

                                                                            Name Type Description Default control_file Path

                                                                            path to the control markdown file

                                                                            required context ControlContext

                                                                            context of the control usage

                                                                            required

                                                                            Returns:

                                                                            Type Description Tuple[Dict[str, List[str]], Dict[str, Dict[str, trestle.core.control_interface.ComponentImpInfo]]]

                                                                            The yaml header as dict in second part of tuple. Adds to the passed in comp_dict.

                                                                            Source code in trestle/core/control_reader.py
                                                                            @staticmethod\ndef read_control_info_from_md(control_file: pathlib.Path,\n                              context: ControlContext) -> Tuple[Dict[str, List[str]], CompDict]:\n\"\"\"\n    Find all labels and associated implementation prose in the markdown for this control.\n\n    Args:\n        control_file: path to the control markdown file\n        context: context of the control usage\n\n    Returns:\n        The yaml header as dict in second part of tuple.\n        Adds to the passed in comp_dict.\n    \"\"\"\n    yaml_header = {}\n    comp_dict = {}\n\n    if not control_file.exists():\n        return yaml_header, comp_dict\n    # if the file exists, load the contents but do not use prose from comp_dict\n    # for non ssp or component mode just use empty string for comp\n    comp_name = ''\n    try:\n        control_id = control_file.stem\n        if context.purpose == ContextPurpose.COMPONENT:\n            comp_name = context.comp_name if context.comp_name else const.SSP_MAIN_COMP_NAME\n\n        md_api = MarkdownAPI()\n        yaml_header, control_md = md_api.processor.process_markdown(control_file)\n\n        # first get the header strings, including statement labels, for statement imp reqs\n        imp_string = '## Implementation '\n        headers = control_md.get_all_headers_for_level(2)\n        # get e.g. ## Implementation a.  ## Implementation b. etc\n        imp_header_list = [header for header in headers if header.startswith(imp_string)]\n\n        # now get the (one) header for the main solution\n        main_headers = list(control_md.get_all_headers_for_key(const.SSP_MD_IMPLEMENTATION_QUESTION, False))\n        # should be only one header, so warn if others found\n        if main_headers:\n            if len(main_headers) > 1:\n                logger.warning(\n                    f'Control {control_id} has {len(main_headers)} main header responses.  Will use first one only.'\n                )\n            main_header = main_headers[0]\n            node = control_md.get_all_nodes_for_keys([main_header], False)[0]\n            # this node is top level so it will have empty label\n            # it may have subnodes of Rules, Implementation Status, Implementaton Remarks\n            ControlReader._add_node_to_dict(comp_name, '', comp_dict, node, control_id, [], context)\n        for imp_header in imp_header_list:\n            label = ControlReader._get_label_from_implementation_header(imp_header)\n            node = control_md.get_node_for_key(imp_header)\n            ControlReader._add_node_to_dict(comp_name, label, comp_dict, node, control_id, [], context)\n\n    except TrestleError as e:\n        raise TrestleError(f'Error occurred reading {control_file}: {e}')\n    return yaml_header, comp_dict\n
                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_editable_content","title":"read_editable_content(control_path, required_sections_list, part_label_to_id_map, cli_section_dict, write_mode) staticmethod","text":"

                                                                            Get parts for the markdown control corresponding to Editable Content - along with the set-parameter dict.

                                                                            Source code in trestle/core/control_reader.py
                                                                            @staticmethod\ndef read_editable_content(\n    control_path: pathlib.Path,\n    required_sections_list: List[str],\n    part_label_to_id_map: Dict[str, Dict[str, str]],\n    cli_section_dict: Dict[str, str],\n    write_mode: bool\n) -> Tuple[str, List[prof.Alter], Dict[str, Any]]:\n\"\"\"Get parts for the markdown control corresponding to Editable Content - along with the set-parameter dict.\"\"\"\n    control_id = control_path.stem\n\n    md_api = MarkdownAPI()\n    yaml_header, control_tree = md_api.processor.process_control_markdown(control_path, cli_section_dict, part_label_to_id_map)  # noqa: E501\n    # extract the sort_id if present in header\n    sort_id = yaml_header.get(const.SORT_ID, control_id)\n\n    editable_node = None\n    for header in list(control_tree.get_all_headers_for_level(1)):\n        if header.startswith('# Editable'):\n            editable_node = control_tree.get_node_for_key(header)\n            break\n    if not editable_node:\n        return sort_id, [], {}\n\n    editable_parts = control_tree.get_editable_parts_and_subparts()\n    by_id_parts = control_tree.get_by_id_parts()\n    found_sections = [p.name for p in editable_parts]\n\n    # Validate that all required sections have a prose\n    for editable_part in editable_parts:\n        if not write_mode and editable_part.name in required_sections_list and editable_part.prose.startswith(\n                const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT):\n            raise TrestleError(f'Control {control_id} is missing prose for required section {editable_part.title}')\n\n    # Validate that all required sections are present\n    missing_sections = set(required_sections_list) - set(found_sections)\n    if missing_sections:\n        raise TrestleError(f'Control {control_id} is missing required sections {missing_sections}')\n    param_dict: Dict[str, Any] = {}\n    # get set_params from the header and add to parm_dict\n    header_params = yaml_header.get(const.SET_PARAMS_TAG, {})\n    if header_params:\n        param_dict.update(header_params)\n\n    props, props_by_id = ControlReader.get_props_list(control_id, part_label_to_id_map, yaml_header)\n\n    # When adding props without by_id it can either be starting or ending and we default to ending\n    # This is the default behavior as described for implicit binding in\n    # https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/\n    # When adding props to a part using by_id, it is the same situation because it cannot be before or after since\n    # props are not in the same list as parts\n\n    adds: List[prof.Add] = []\n\n    # add the parts and props at control level\n    if editable_parts or props:\n        adds.append(\n            prof.Add(\n                parts=none_if_empty(editable_parts),\n                props=none_if_empty(props),\n                position=prof.PositionValidValues.ending.value\n            )\n        )\n\n    # add the parts and props at the part level, by-id\n    by_ids = set(by_id_parts.keys()).union(props_by_id.keys())\n    for by_id in sorted(by_ids):\n        parts = by_id_parts.get(by_id, None)\n        props = props_by_id.get(by_id, None)\n        adds.append(prof.Add(parts=parts, props=props, position=prof.PositionValidValues.ending.value, by_id=by_id))\n\n    new_alters = []\n    if adds:\n        new_alters = [prof.Alter(control_id=control_id, adds=adds)]\n    return sort_id, new_alters, param_dict\n
                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.read_implemented_requirement","title":"read_implemented_requirement(control_file, context) staticmethod","text":"

                                                                            Get the implementated requirement associated with given control and link to existing components or new ones.

                                                                            Parameters:

                                                                            Name Type Description Default control_file Path

                                                                            path of the control markdown file

                                                                            required context ControlContext

                                                                            context of the control usage

                                                                            required

                                                                            Returns:

                                                                            Type Description Tuple

                                                                            The control sort-id and the one implemented requirement for this control.

                                                                            Notes

                                                                            Each statement may have several responses, with each response in a by_component for a specific component. statement_map keeps track of statements that may have several by_component responses. This is only used during component assemble and only for updating one component.

                                                                            Source code in trestle/core/control_reader.py
                                                                            @staticmethod\ndef read_implemented_requirement(control_file: pathlib.Path,\n                                 context: ControlContext) -> Tuple[str, comp.ImplementedRequirement]:\n\"\"\"\n    Get the implementated requirement associated with given control and link to existing components or new ones.\n\n    Args:\n        control_file: path of the control markdown file\n        context: context of the control usage\n\n    Returns:\n        Tuple: The control sort-id and the one implemented requirement for this control.\n\n    Notes:\n        Each statement may have several responses, with each response in a by_component for a specific component.\n        statement_map keeps track of statements that may have several by_component responses.\n        This is only used during component assemble and only for updating one component.\n    \"\"\"\n    control_id = control_file.stem\n    md_header, md_comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n    comp_name = context.component.title\n\n    statement_map: Dict[str, comp.Statement] = {}\n    # create a new implemented requirement linked to the control id to hold the statements\n    imp_req = gens.generate_sample_model(comp.ImplementedRequirement)\n    imp_req.control_id = control_id\n\n    imp_req.statements = []\n    comp_dict = md_comp_dict[comp_name]\n    for label, comp_info in comp_dict.items():\n        # only assemble responses with associated rules\n        if not comp_info.rules:\n            continue\n        # if no label it applies to the imp_req itself rather than a statement\n        if not label:\n            imp_req.description = ControlReader._handle_empty_prose(comp_info.prose, control_id)\n            ControlInterface.insert_status_in_props(imp_req, comp_info.status)\n            continue\n        statement_id = ControlInterface.create_statement_id(control_id)\n        if label in ['', const.STATEMENT]:\n            statement_part_id = statement_id\n        else:\n            clean_label = label.strip('.')\n            statement_part_id = ControlInterface.strip_to_make_ncname(f'{statement_id}.{clean_label}')\n        if statement_part_id in statement_map:\n            statement = statement_map[statement_part_id]\n        else:\n            statement = gens.generate_sample_model(comp.Statement)\n            statement.statement_id = statement_part_id\n            statement_map[statement_part_id] = statement\n        statement.description = comp_info.prose\n        statement.props = none_if_empty(ControlInterface.clean_props(comp_info.props))\n        ControlInterface.insert_status_in_props(statement, comp_info.status)\n\n    imp_req.statements = list(statement_map.values())\n    imp_req.set_parameters = []\n\n    for _, param_dict_list in md_header.get(const.COMP_DEF_RULES_PARAM_VALS_TAG, {}).items():\n        for param_dict in param_dict_list:\n            values = param_dict.get(const.VALUES, [])\n            comp_values = param_dict.get(const.COMPONENT_VALUES, [])\n            values = comp_values if comp_values else values\n            set_param = ossp.SetParameter(param_id=param_dict['name'], values=values)\n            imp_req.set_parameters.append(set_param)\n    imp_req.statements = none_if_empty(list(statement_map.values()))\n    imp_req.set_parameters = none_if_empty(imp_req.set_parameters)\n\n    ControlReader._insert_header_content(imp_req, md_header, control_id)\n    sort_id = md_header.get(const.SORT_ID, control_id)\n    return sort_id, imp_req\n
                                                                            "},{"location":"api_reference/trestle.core.control_reader/#trestle.core.control_reader.ControlReader.simplify_name","title":"simplify_name(name) staticmethod","text":"

                                                                            Simplify the name to ignore variations in case, space, hyphen, underscore, slash.

                                                                            Source code in trestle/core/control_reader.py
                                                                            @staticmethod\ndef simplify_name(name: str) -> str:\n\"\"\"Simplify the name to ignore variations in case, space, hyphen, underscore, slash.\"\"\"\n    return name.lower().replace(' ', '').replace('-', '').replace('_', '').replace('/', '')\n
                                                                            "},{"location":"api_reference/trestle.core.control_writer/","title":"control_writer","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer","title":"trestle.core.control_writer","text":"

                                                                            Handle writing of controls to markdown.

                                                                            "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter","title":" ControlWriter ","text":"

                                                                            Class to write controls as markdown.

                                                                            Source code in trestle/core/control_writer.py
                                                                            class ControlWriter():\n\"\"\"Class to write controls as markdown.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize the class.\"\"\"\n        self._md_file: Optional[MDWriter] = None\n\n    def _add_part_and_its_items(self, control: cat.Control, name: str, item_type: str) -> None:\n\"\"\"For a given control add its one statement and its items to the md file after replacing params.\"\"\"\n        items = []\n        if control.parts:\n            for part in control.parts:\n                if part.name == name:\n                    # If the part has prose write it as a raw line and not list element\n                    skip_id = part.id\n                    if part.prose:\n                        self._md_file.new_line(part.prose)\n                    items.append(ControlInterface.get_part(part, item_type, skip_id))\n            # unwrap the list if it is many levels deep\n            while not isinstance(items, str) and len(items) == 1:\n                items = items[0]\n            self._md_file.new_paragraph()\n            self._md_file.new_list(items)\n\n    def _add_yaml_header(self, yaml_header: Optional[Dict]) -> None:\n        if yaml_header:\n            self._md_file.add_yaml_header(yaml_header)\n\n    def _add_control_statement(self, control: cat.Control, group_title: str, print_group_title=True) -> None:\n\"\"\"Add the control statement and items to the md file.\"\"\"\n        self._md_file.new_paragraph()\n        control_id = control.id\n        group_name = ''\n        control_title = control.title\n\n        if print_group_title:\n            group_name = ' \\[' + group_title + '\\]'\n\n        title = f'{control_id} -{group_name} {control_title}'\n\n        header_title = 'Control Statement'\n        self._md_file.new_header(level=1, title=title)\n        self._md_file.new_header(level=2, title=header_title)\n        self._md_file.set_indent_level(-1)\n        self._add_part_and_its_items(control, const.STATEMENT, const.ITEM)\n        self._md_file.set_indent_level(-1)\n\n    def _add_control_objective(self, control: cat.Control) -> None:\n        if control.parts:\n            for part in control.parts:\n                if part.name == const.OBJECTIVE_PART or part.name == const.ASSESMENT_OBJECTIVE_PART:\n                    self._md_file.new_paragraph()\n                    heading_title = 'Control Objective'\n                    if part.name == const.ASSESMENT_OBJECTIVE_PART:\n                        heading_title = 'Control Assessment Objective'\n                    self._md_file.new_header(level=2, title=heading_title)\n                    self._md_file.set_indent_level(-1)\n                    self._add_part_and_its_items(control, part.name, part.name)\n                    self._md_file.set_indent_level(-1)\n                    return\n\n    def _add_sections(self, control: cat.Control, allowed_sections: Optional[List[str]]) -> None:\n\"\"\"Add the extra control sections after the main ones.\"\"\"\n        skip_section_list = [const.STATEMENT, const.ITEM, const.OBJECTIVE_PART, const.ASSESMENT_OBJECTIVE_PART]\n        while True:\n            _, name, title, prose = ControlInterface.get_section(control, skip_section_list)\n            if not name:\n                return\n            if allowed_sections and name not in allowed_sections:\n                skip_section_list.append(name)\n                continue\n            if prose:\n                # section title will be from the section_dict, the part title, or the part name in that order\n                # this way the user-provided section title can override the part title\n                section_title = self._sections_dict.get(name, title) if self._sections_dict else title\n                section_title = section_title if section_title else name\n                skip_section_list.append(name)\n                self._md_file.new_header(level=2, title=f'Control {section_title}')\n                self._md_file.new_line(prose)\n                self._md_file.new_paragraph()\n\n    def _insert_status(self, status: ImplementationStatus, level: int) -> None:\n        self._md_file.new_header(level=level, title=f'{const.IMPLEMENTATION_STATUS_HEADER}: {status.state}')\n        # this used to output remarks also\n\n    def _insert_rules(self, rules: List[str], level: int) -> None:\n        if rules:\n            self._md_file.new_header(level=level, title='Rules:')\n            self._md_file.set_indent_level(0)\n            self._md_file.new_list(rules)\n            self._md_file.set_indent_level(-1)\n\n    def _insert_comp_info(\n        self, part_label: str, comp_info: Dict[str, ComponentImpInfo], context: ControlContext\n    ) -> None:\n\"\"\"Insert prose and status from the component info.\"\"\"\n        level = 3 if context.purpose == ContextPurpose.COMPONENT else 4\n        if part_label in comp_info:\n            info = comp_info[part_label]\n            if context.purpose in [ContextPurpose.COMPONENT, ContextPurpose.SSP] and not info.rules:\n                return\n            self._md_file.new_paragraph()\n            if info.prose:\n                self._md_file.new_line(info.prose)\n            else:\n                self._md_file.new_line(f'{const.SSP_ADD_IMPLEMENTATION_FOR_ITEM_TEXT} {part_label} -->')\n\n            self._insert_rules(info.rules, level)\n            self._insert_status(info.status, level)\n        else:\n            self._insert_status(ImplementationStatus(state=const.STATUS_PLANNED), level)\n\n    def _process_main_component(self, part_id: str, part_label: str, comp_dict: CompDict) -> None:\n\"\"\"Handle prompts for This System component.\"\"\"\n        self._md_file.new_paragraph()\n        self._md_file.new_header(3, const.SSP_MAIN_COMP_NAME)\n        self._md_file.new_paragraph()\n        prose = f'{const.SSP_ADD_THIS_SYSTEM_IMPLEMENTATION_FOR_CONTROL_TEXT}: {part_id} -->'\n        status = ImplementationStatus(state=const.STATUS_PLANNED)\n        sys_comp_dict: Dict[str, ComponentImpInfo] = comp_dict.get(const.SSP_MAIN_COMP_NAME, {})\n        if sys_comp_dict and part_label in sys_comp_dict:\n            comp_info = sys_comp_dict[part_label]\n            if comp_info.prose:\n                prose = comp_info.prose\n            status = comp_info.status\n        self._md_file.new_paraline(prose)\n        self._insert_status(status, 4)\n\n    def _add_component_control_prompts(self, control_id: str, comp_dict: CompDict, context: ControlContext) -> bool:\n\"\"\"Add prompts to the markdown for the control itself, per component.\"\"\"\n        if context.purpose not in [ContextPurpose.COMPONENT, ContextPurpose.SSP]:\n            return False\n        self._md_file.new_paraline(const.STATUS_PROMPT)\n        self._md_file.new_paraline(const.RULES_WARNING)\n        did_write = False\n        # do special handling for This System\n        if context.purpose == ContextPurpose.SSP:\n            # Passing in the control id and the empty key ('') for the label\n            self._process_main_component(control_id, '', comp_dict)\n            did_write = True\n\n        sorted_comp_names = sorted(comp_dict.keys())\n        for comp_name in sorted_comp_names:\n            dic = comp_dict[comp_name]\n            # This System already handled\n            if comp_name == const.SSP_MAIN_COMP_NAME:\n                continue\n            for comp_info in [val for key, val in dic.items() if key == '']:\n                # don't output component name for component markdown since only one component\n                if context.purpose != ContextPurpose.COMPONENT:\n                    self._md_file.new_header(3, comp_name)\n                prose = comp_info.prose if comp_info.prose != control_id else ''\n                if not prose:\n                    prose = f'{const.SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT}: {control_id} -->'\n                self._md_file.new_paraline(prose)\n                level = 3 if context.purpose == ContextPurpose.COMPONENT else 4\n                self._insert_rules(comp_info.rules, level)\n                self._insert_status(comp_info.status, level)\n                did_write = True\n        return did_write\n\n    def _add_implementation_response_prompts(\n        self, control: cat.Control, comp_dict: CompDict, context: ControlContext\n    ) -> None:\n\"\"\"Add the response request text for all parts to the markdown along with the header.\"\"\"\n        self._md_file.new_hr()\n        self._md_file.new_paragraph()\n        # top level request for implementation details\n        self._md_file.new_header(level=2, title=f'{const.SSP_MD_IMPLEMENTATION_QUESTION}')\n\n        # write out control level prose and status\n        did_write_part = self._add_component_control_prompts(control.id, comp_dict, context)\n\n        # if the control has no parts written out then enter implementation in the top level entry\n        # but if it does have parts written out, leave top level blank and provide details in the parts\n        # Note that parts corresponding to sections don't get written out here so a check is needed\n        # If we have responses per component then enter them in separate ### sections\n        if control.parts:\n            for part in control.parts:\n                if part.parts and part.name == const.STATEMENT:\n                    for prt in part.parts:\n                        if prt.name != const.ITEM:\n                            continue\n                        # if no label guess the label from the sub-part id\n                        part_label = ControlInterface.get_label(prt)\n                        part_label = prt.id.split('.')[-1] if not part_label else part_label\n\n                        # Determine if this part should be written out\n                        if self._skip_part(context, part_label, comp_dict):\n                            continue\n\n                        if not did_write_part:\n                            self._md_file.new_line(const.SSP_MD_LEAVE_BLANK_TEXT)\n                            # insert extra line to make mdformat happy\n                            self._md_file._add_line_raw('')\n                        self._md_file.new_hr()\n                        self._md_file.new_header(level=2, title=f'Implementation for part {part_label}')\n                        wrote_label_content = False\n                        # To reduce verbosity by default, the main component\n                        # is conditionally written for each part dependant on the control context.\n                        if context.purpose == ContextPurpose.SSP and context.include_all_parts:\n                            self._process_main_component(prt.id, part_label, comp_dict)\n                            wrote_label_content = True\n                        sorted_comp_names = sorted(comp_dict.keys())\n                        for comp_name in sorted_comp_names:\n                            # This System already handled\n                            if comp_name == const.SSP_MAIN_COMP_NAME:\n                                continue\n                            dic = comp_dict[comp_name]\n                            if part_label in dic:\n                                # insert the component name for ssp but not for comp_def\n                                # because there should only be one component in generated comp_def markdown\n                                if context.purpose != ContextPurpose.COMPONENT:\n                                    self._md_file.new_header(level=3, title=comp_name)\n                                self._insert_comp_info(part_label, dic, context)\n                                wrote_label_content = True\n                        if not wrote_label_content:\n                            level = 3 if context.purpose == ContextPurpose.COMPONENT else 4\n                            self._insert_status(ImplementationStatus(state=const.STATUS_PLANNED), level)\n                        self._md_file.new_paragraph()\n                        did_write_part = True\n        # if we loaded nothing for this control yet then it must need a fresh prompt for the control statement\n        if not comp_dict and not did_write_part:\n            self._md_file.new_line(f'{const.SSP_ADD_IMPLEMENTATION_FOR_CONTROL_TEXT}: {control.id} -->')\n            if context.purpose in [ContextPurpose.COMPONENT, ContextPurpose.SSP]:\n                status = ControlInterface.get_status_from_props(control)\n                self._insert_status(status, 3)\n        if not did_write_part:\n            part_label = ''\n            for comp_name, dic in comp_dict.items():\n                if part_label in dic:\n                    if comp_name != const.SSP_MAIN_COMP_NAME:\n                        self._md_file.new_header(level=3, title=comp_name)\n                    self._insert_comp_info(part_label, dic, context)\n        self._md_file.new_hr()\n\n    def _skip_part(self, context: ControlContext, part_label: str, comp_dict: CompDict) -> bool:\n\"\"\"\n        Check if a part should be skipped based on rules and context.\n\n        Notes: The default logic is to conditionally add control parts based\n        on whether the component has rules associated with that part. This can be\n        changed using the control context for SSP markdown.\n        \"\"\"\n        if context.purpose == ContextPurpose.SSP and context.include_all_parts:\n            return False\n        else:\n            no_applied_rules = True\n            for _, dic in comp_dict.items():\n                if part_label in dic and dic[part_label].rules:\n                    no_applied_rules = False\n                    break\n        return no_applied_rules\n\n    def _dump_subpart_infos(self, level: int, part: Dict[str, Any]) -> None:\n        name = part['name']\n        title = self._sections_dict.get(name, name) if self._sections_dict else name\n        self._md_file.new_header(level=level, title=title)\n        if 'prose' in part:\n            self._md_file.new_paraline(part['prose'])\n        for subpart in as_list(part.get('parts', None)):\n            self._dump_subpart_infos(level + 1, subpart)\n\n    def _dump_subparts(self, level: int, part: Part) -> None:\n        name = part.name\n        title = self._sections_dict.get(name, name) if self._sections_dict else name\n        self._md_file.new_header(level=level, title=title)\n        if part.prose:\n            self._md_file.new_paraline(part.prose)\n        for subpart in as_list(part.parts):\n            self._dump_subparts(level + 1, subpart)\n\n    def _dump_section(self, level: int, part: Part, added_sections: List[str], prefix: str) -> None:\n        title = self._sections_dict.get(part.name, part.name) if self._sections_dict else part.name\n        title = f'{prefix} {title}' if prefix else title\n        self._md_file.new_header(level=level, title=title)\n        if part.prose:\n            self._md_file.new_paraline(part.prose)\n        for subpart in as_list(part.parts):\n            self._dump_subparts(level + 1, subpart)\n        added_sections.append(part.name)\n\n    def _dump_section_info(self, level: int, part: Dict[str, Any], added_sections: List[str], prefix: str) -> None:\n        part_prose = part.get('prose', None)\n        part_subparts = part.get('parts', None)\n        name = part['name']\n        title = self._sections_dict.get(name, name) if self._sections_dict else name\n        title = f'{prefix} {title}' if prefix else title\n        self._md_file.new_header(level=level, title=title)\n        if part_prose:\n            self._md_file.new_paraline(part_prose)\n        for subpart in as_list(part_subparts):\n            self._dump_subpart_infos(level + 1, subpart)\n        added_sections.append(name)\n\n    def _add_additional_content(\n        self,\n        control: cat.Control,\n        profile: prof.Profile,\n        header: Dict[str, Any],\n        part_id_map: Dict[str, str],\n        found_alters: List[prof.Alter]\n    ) -> List[str]:\n        # get part and subpart info from adds of the profile\n        part_infos = ControlInterface.get_all_add_info(control.id, profile)\n        has_content = len(part_infos) > 0\n\n        self._md_file.new_header(level=1, title=const.EDITABLE_CONTENT)\n        self._md_file.new_line('<!-- Make additions and edits below -->')\n        self._md_file.new_line(\n            '<!-- The above represents the contents of the control as received by the profile, prior to additions. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- If the profile makes additions to the control, they will appear below. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- The above markdown may not be edited but you may edit the content below, and/or introduce new additions to be made by the profile. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- If there is a yaml header at the top, parameter values may be edited. Use --set-parameters to incorporate the changes during assembly. -->'  # noqa E501\n        )\n        self._md_file.new_line(\n            '<!-- The content here will then replace what is in the profile for this control, after running profile-assemble. -->'  # noqa E501\n        )\n        if has_content:\n            self._md_file.new_line(\n                '<!-- The added parts in the profile for this control are below.  You may edit them and/or add new ones. -->'  # noqa E501\n            )\n        else:\n            self._md_file.new_line(\n                '<!-- The current profile has no added parts for this control, but you may add new ones here. -->'\n            )\n        self._md_file.new_line(\n            '<!-- Each addition must have a heading either of the form ## Control my_addition_name -->'\n        )\n        self._md_file.new_line('<!-- or ## Part a. (where the a. refers to one of the control statement labels.) -->')\n        self._md_file.new_line('<!-- \"## Control\" parts are new parts added after the statement part. -->')\n        self._md_file.new_line(\n            '<!-- \"## Part\" parts are new parts added into the top-level statement part with that label. -->'\n        )\n        self._md_file.new_line('<!-- Subparts may be added with nested hash levels of the form ### My Subpart Name -->')\n        self._md_file.new_line('<!-- underneath the parent ## Control or ## Part being added -->')\n        self._md_file.new_line(\n            '<!-- See https://oscal-compass.github.io/compliance-trestle/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring for guidance. -->'  # noqa E501\n        )\n        # next is to make mdformat happy\n        self._md_file._add_line_raw('')\n\n        added_sections: List[str] = []\n\n        control_part_id_map = part_id_map.get(control.id, {})\n        statement_id = ControlInterface.get_statement_id(control)\n\n        # if the file already has markdown content, read its alters\n        if self._md_file.exists():\n            if const.TRESTLE_ADD_PROPS_TAG in header:\n                header.pop(const.TRESTLE_ADD_PROPS_TAG)\n            for alter in found_alters:\n                for add in as_list(alter.adds):\n                    # by_id could refer to statement (Control) or part (Part)\n                    if add.by_id:\n                        # is this a part that goes after the control statement\n                        if add.by_id == statement_id:\n                            for part in as_list(add.parts):\n                                if part.prose or part.parts:\n                                    self._dump_section(2, part, added_sections, 'Control')\n                        else:\n                            # or is it a sub-part of a statement part\n                            part_label = control_part_id_map.get(add.by_id, add.by_id)\n                            if add.parts:\n                                self._md_file.new_header(level=2, title=f'Part {part_label}')\n                                for part in as_list(add.parts):\n                                    if part.prose or part.parts:\n                                        name = part.name\n                                        # need special handling for statement parts because their name is 'item'\n                                        # get the short name as last piece of the part id after the '.'\n                                        if name == const.ITEM:\n                                            name = part.id.split('.')[-1]\n                                        title = self._sections_dict.get(name, name) if self._sections_dict else name\n                                        self._md_file.new_header(level=3, title=title)\n                                        if part.prose:\n                                            self._md_file.new_paraline(part.prose)\n                                        for subpart in as_list(part.parts):\n                                            self._dump_subparts(3, subpart)\n                                        added_sections.append(name)\n                    else:\n                        # if not by_id just add at end of control's parts\n                        for part in as_list(add.parts):\n                            if part.prose or part.parts:\n                                self._dump_section(2, part, added_sections, 'Control')\n                    if add.props:\n                        if const.TRESTLE_ADD_PROPS_TAG not in header:\n                            header[const.TRESTLE_ADD_PROPS_TAG] = []\n                        by_id = add.by_id\n                        part_info = PartInfo(name='', prose='', props=add.props, smt_part=by_id)\n                        _, prop_list = part_info.to_dicts(part_id_map.get(control.id, {}))\n                        header[const.TRESTLE_ADD_PROPS_TAG].extend(prop_list)\n        else:\n            # md does not already exist so fill in directly\n            in_part = ''\n            for part_info in part_infos:\n                part, prop_list = part_info.to_dicts(part_id_map.get(control.id, {}))\n                # is this part of a statement part\n                if part_info.smt_part and part_info.prose and part_info.smt_part in control_part_id_map:\n                    # avoid outputting ## Part again if in same part\n                    if not part_info.smt_part == in_part:\n                        in_part = part_info.smt_part\n                        part_label = control_part_id_map.get(part_info.smt_part, part_info.smt_part)\n                        self._md_file.new_header(level=2, title=f'Part {part_label}')\n                    self._dump_section_info(3, part, added_sections, '')\n                # is it a control part\n                elif part_info.prose or part_info.parts:\n                    in_part = ''\n                    self._dump_section_info(2, part, added_sections, 'Control')\n                elif prop_list:\n                    in_part = ''\n                    if const.TRESTLE_ADD_PROPS_TAG not in header:\n                        header[const.TRESTLE_ADD_PROPS_TAG] = []\n                    header[const.TRESTLE_ADD_PROPS_TAG].extend(prop_list)\n        return added_sections\n\n    def _prompt_required_sections(self, required_sections: List[str], added_sections: List[str]) -> None:\n\"\"\"Add prompts for any required sections that haven't already been written out.\"\"\"\n        missing_sections = set(required_sections).difference(added_sections)\n        for section in sorted(missing_sections):\n            section_title = self._sections_dict.get(section, section)\n            self._md_file.new_header(2, f'Control {section_title}')\n            self._md_file.new_line(f'{const.PROFILE_ADD_REQUIRED_SECTION_FOR_CONTROL_TEXT}: {section_title} -->')\n\n    @staticmethod\n    def _merge_headers(memory_header: Dict[str, Any], md_header: Dict[str, Any],\n                       context: ControlContext) -> Dict[str, Any]:\n        merged_header = copy.deepcopy(md_header)\n        ControlInterface.merge_dicts_deep(merged_header, memory_header, False, 1)\n        return merged_header\n\n    def write_control_for_editing(\n        self,\n        context: ControlContext,\n        control: cat.Control,\n        dest_path: pathlib.Path,\n        group_title: str,\n        part_id_map: Dict[str, str],\n        found_alters: List[prof.Alter]\n    ) -> None:\n\"\"\"\n        Write out the control in markdown format into the specified directory.\n\n        Args:\n            context: The context of the control usage\n            control: The control to write as markdown\n            dest_path: Path to the directory where the control will be written\n            group_title: Title of the group containing the control\n            part_id_map: Mapping of part_id to label\n            found_alters: List of alters read from the markdown file - if it exists\n\n        Returns:\n            None\n\n        Notes:\n            The filename is constructed from the control's id and created in the dest_path.\n            If a yaml header is present in the file, new values in provided header will not replace those in the\n            markdown header unless overwrite_header_values is true.  If it is true then overwrite any existing values,\n            but in all cases new items from the provided header will be added to the markdown header.\n            If the markdown file already exists, its current header and prose are read.\n            Controls are checked if they are marked withdrawn, and if so they are not written out.\n        \"\"\"\n        if ControlInterface.is_withdrawn(control):\n            logger.debug(f'Not writing out control {control.id} since it is marked Withdrawn.')\n            return\n\n        control_file = dest_path / (control.id + const.MARKDOWN_FILE_EXT)\n        # read the existing markdown header and content if it exists\n        md_header, comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n        # replace the memory comp_dict with the md one if control exists\n        if comp_dict:\n            context.comp_dict = comp_dict\n\n        header_comment_dict = {const.TRESTLE_ADD_PROPS_TAG: const.YAML_PROPS_COMMENT}\n        if context.to_markdown:\n            if context.purpose == ContextPurpose.PROFILE:\n                header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_PROFILE_VALUES_COMMENT\n            elif context.purpose == ContextPurpose.SSP:\n                header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_SSP_VALUES_COMMENT\n                header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG] = const.YAML_RULE_PARAM_VALUES_SSP_COMMENT\n                # The add props information to SSP only. It is added to the profile later.\n                if const.TRESTLE_ADD_PROPS_TAG not in md_header:\n                    md_header[const.TRESTLE_ADD_PROPS_TAG] = []\n            elif context.purpose == ContextPurpose.COMPONENT:\n                header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG\n                                    ] = const.YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT\n\n        # begin adding info to the md file\n        self._md_file = MDWriter(control_file, header_comment_dict)\n        self._sections_dict = context.sections_dict\n\n        context.merged_header = ControlWriter._merge_headers(context.merged_header, md_header, context)\n        # if the control has an explicitly defined sort-id and there is none in the yaml_header, then insert it\n        # in the yaml header and allow overwrite_header_values to control whether it overwrites an existing one\n        # in the markdown header\n        context.cli_yaml_header = as_dict(context.cli_yaml_header)\n        if context.purpose != ContextPurpose.PROFILE:\n            ControlInterface.merge_dicts_deep(\n                context.merged_header, context.cli_yaml_header, context.overwrite_header_values\n            )\n        # the global contents are special and get overwritten on generate\n        set_or_pop(\n            context.merged_header,\n            const.TRESTLE_GLOBAL_TAG,\n            context.cli_yaml_header.get(const.TRESTLE_GLOBAL_TAG, None)\n        )\n        sort_id = ControlInterface.get_sort_id(control, True)\n        if sort_id:\n            deep_set(context.merged_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], sort_id)\n\n        # merge any provided sections with sections in the header, with priority to the one from context (e.g. CLI)\n        header_sections_dict = context.merged_header.get(const.SECTIONS_TAG, {})\n        merged_sections_dict = merge_dicts(header_sections_dict, context.sections_dict)\n        set_or_pop(context.merged_header, const.SECTIONS_TAG, merged_sections_dict)\n\n        # now begin filling in content from the control in memory\n        self._add_control_statement(control, group_title)\n\n        self._add_control_objective(control)\n\n        # add allowed sections to the markdown\n        self._add_sections(control, context.allowed_sections)\n\n        # prompt responses for imp reqs using special format if comp_def mode\n        if context.prompt_responses:\n            self._add_implementation_response_prompts(control, context.comp_dict, context)\n\n        # for profile generate\n        # add sections corresponding to added parts in the profile\n        added_sections: List[str] = []\n        if context.purpose == ContextPurpose.PROFILE:\n            added_sections = self._add_additional_content(\n                control, context.profile, context.merged_header, part_id_map, found_alters\n            )\n\n        self._add_yaml_header(context.merged_header)\n\n        if context.required_sections:\n            self._prompt_required_sections(context.required_sections, added_sections)\n\n        self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter.__init__","title":"__init__(self) special","text":"

                                                                            Initialize the class.

                                                                            Source code in trestle/core/control_writer.py
                                                                            def __init__(self):\n\"\"\"Initialize the class.\"\"\"\n    self._md_file: Optional[MDWriter] = None\n
                                                                            "},{"location":"api_reference/trestle.core.control_writer/#trestle.core.control_writer.ControlWriter.write_control_for_editing","title":"write_control_for_editing(self, context, control, dest_path, group_title, part_id_map, found_alters)","text":"

                                                                            Write out the control in markdown format into the specified directory.

                                                                            Parameters:

                                                                            Name Type Description Default context ControlContext

                                                                            The context of the control usage

                                                                            required control Control

                                                                            The control to write as markdown

                                                                            required dest_path Path

                                                                            Path to the directory where the control will be written

                                                                            required group_title str

                                                                            Title of the group containing the control

                                                                            required part_id_map Dict[str, str]

                                                                            Mapping of part_id to label

                                                                            required found_alters List[trestle.oscal.profile.Alter]

                                                                            List of alters read from the markdown file - if it exists

                                                                            required

                                                                            Returns:

                                                                            Type Description None

                                                                            None

                                                                            Notes

                                                                            The filename is constructed from the control's id and created in the dest_path. If a yaml header is present in the file, new values in provided header will not replace those in the markdown header unless overwrite_header_values is true. If it is true then overwrite any existing values, but in all cases new items from the provided header will be added to the markdown header. If the markdown file already exists, its current header and prose are read. Controls are checked if they are marked withdrawn, and if so they are not written out.

                                                                            Source code in trestle/core/control_writer.py
                                                                            def write_control_for_editing(\n    self,\n    context: ControlContext,\n    control: cat.Control,\n    dest_path: pathlib.Path,\n    group_title: str,\n    part_id_map: Dict[str, str],\n    found_alters: List[prof.Alter]\n) -> None:\n\"\"\"\n    Write out the control in markdown format into the specified directory.\n\n    Args:\n        context: The context of the control usage\n        control: The control to write as markdown\n        dest_path: Path to the directory where the control will be written\n        group_title: Title of the group containing the control\n        part_id_map: Mapping of part_id to label\n        found_alters: List of alters read from the markdown file - if it exists\n\n    Returns:\n        None\n\n    Notes:\n        The filename is constructed from the control's id and created in the dest_path.\n        If a yaml header is present in the file, new values in provided header will not replace those in the\n        markdown header unless overwrite_header_values is true.  If it is true then overwrite any existing values,\n        but in all cases new items from the provided header will be added to the markdown header.\n        If the markdown file already exists, its current header and prose are read.\n        Controls are checked if they are marked withdrawn, and if so they are not written out.\n    \"\"\"\n    if ControlInterface.is_withdrawn(control):\n        logger.debug(f'Not writing out control {control.id} since it is marked Withdrawn.')\n        return\n\n    control_file = dest_path / (control.id + const.MARKDOWN_FILE_EXT)\n    # read the existing markdown header and content if it exists\n    md_header, comp_dict = ControlReader.read_control_info_from_md(control_file, context)\n    # replace the memory comp_dict with the md one if control exists\n    if comp_dict:\n        context.comp_dict = comp_dict\n\n    header_comment_dict = {const.TRESTLE_ADD_PROPS_TAG: const.YAML_PROPS_COMMENT}\n    if context.to_markdown:\n        if context.purpose == ContextPurpose.PROFILE:\n            header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_PROFILE_VALUES_COMMENT\n        elif context.purpose == ContextPurpose.SSP:\n            header_comment_dict[const.SET_PARAMS_TAG] = const.YAML_SSP_VALUES_COMMENT\n            header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG] = const.YAML_RULE_PARAM_VALUES_SSP_COMMENT\n            # The add props information to SSP only. It is added to the profile later.\n            if const.TRESTLE_ADD_PROPS_TAG not in md_header:\n                md_header[const.TRESTLE_ADD_PROPS_TAG] = []\n        elif context.purpose == ContextPurpose.COMPONENT:\n            header_comment_dict[const.COMP_DEF_RULES_PARAM_VALS_TAG\n                                ] = const.YAML_RULE_PARAM_VALUES_COMPONENT_COMMENT\n\n    # begin adding info to the md file\n    self._md_file = MDWriter(control_file, header_comment_dict)\n    self._sections_dict = context.sections_dict\n\n    context.merged_header = ControlWriter._merge_headers(context.merged_header, md_header, context)\n    # if the control has an explicitly defined sort-id and there is none in the yaml_header, then insert it\n    # in the yaml header and allow overwrite_header_values to control whether it overwrites an existing one\n    # in the markdown header\n    context.cli_yaml_header = as_dict(context.cli_yaml_header)\n    if context.purpose != ContextPurpose.PROFILE:\n        ControlInterface.merge_dicts_deep(\n            context.merged_header, context.cli_yaml_header, context.overwrite_header_values\n        )\n    # the global contents are special and get overwritten on generate\n    set_or_pop(\n        context.merged_header,\n        const.TRESTLE_GLOBAL_TAG,\n        context.cli_yaml_header.get(const.TRESTLE_GLOBAL_TAG, None)\n    )\n    sort_id = ControlInterface.get_sort_id(control, True)\n    if sort_id:\n        deep_set(context.merged_header, [const.TRESTLE_GLOBAL_TAG, const.SORT_ID], sort_id)\n\n    # merge any provided sections with sections in the header, with priority to the one from context (e.g. CLI)\n    header_sections_dict = context.merged_header.get(const.SECTIONS_TAG, {})\n    merged_sections_dict = merge_dicts(header_sections_dict, context.sections_dict)\n    set_or_pop(context.merged_header, const.SECTIONS_TAG, merged_sections_dict)\n\n    # now begin filling in content from the control in memory\n    self._add_control_statement(control, group_title)\n\n    self._add_control_objective(control)\n\n    # add allowed sections to the markdown\n    self._add_sections(control, context.allowed_sections)\n\n    # prompt responses for imp reqs using special format if comp_def mode\n    if context.prompt_responses:\n        self._add_implementation_response_prompts(control, context.comp_dict, context)\n\n    # for profile generate\n    # add sections corresponding to added parts in the profile\n    added_sections: List[str] = []\n    if context.purpose == ContextPurpose.PROFILE:\n        added_sections = self._add_additional_content(\n            control, context.profile, context.merged_header, part_id_map, found_alters\n        )\n\n    self._add_yaml_header(context.merged_header)\n\n    if context.required_sections:\n        self._prompt_required_sections(context.required_sections, added_sections)\n\n    self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/","title":"bycomp_interface","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface","title":"trestle.core.crm.bycomp_interface","text":"

                                                                            Provide interface to by-component allowing queries and operations for exports/inheritance statements.

                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface","title":" ByComponentInterface ","text":"

                                                                            Interface to query and modify by-component assembly inheritance contents.

                                                                            The by-component is contained in two separate forms: As an actual OSCAL by-component assembly, and multiple dicts providing direct lookup of inheritance statement by uuid.

                                                                            The dicts are created by the ByComponentInterface constructor, parsed and the responsibility and provided statements are separated into three catagories:

                                                                            isolated responsibilities - A responsibility with no provided statement isolated provided - A provided statement with no referring responsibility statements export set - A set with a single responsibility and referred provided statement

                                                                            For updating ByComponent inheritance and satisfied statements, the interface provides a method to reconcile the the by-component assembly and merge input inherited and satisfied statements.

                                                                            Source code in trestle/core/crm/bycomp_interface.py
                                                                            class ByComponentInterface:\n\"\"\"\n    Interface to query and modify by-component assembly inheritance contents.\n\n    The by-component is contained in two separate forms:  As an actual OSCAL by-component assembly,\n    and multiple dicts providing direct lookup of inheritance statement by uuid.\n\n    The dicts are created by the ByComponentInterface constructor, parsed and the responsibility and provided statements\n    are separated into three catagories:\n\n    isolated responsibilities - A responsibility with no provided statement\n    isolated provided - A provided statement with no referring responsibility statements\n    export set - A set with a single responsibility and referred provided statement\n\n    For updating ByComponent inheritance and satisfied statements, the interface provides a method to reconcile the\n    the by-component assembly and merge input inherited and satisfied statements.\n    \"\"\"\n\n    def __init__(self, by_comp: ossp.ByComponent):\n\"\"\"Initialize export writer for a single by-component assembly.\"\"\"\n        self._by_comp: ossp.ByComponent = by_comp\n\n        self._provided_dict: Dict[str, ossp.Provided] = {}\n        self._responsibility_dict: Dict[str, ossp.Responsibility] = {}\n        self._responsibility_by_provided: Dict[str, List[ossp.Responsibility]] = {}\n\n        self._inherited_dict: Dict[str, ossp.Inherited] = self._create_inherited_dict()\n        self._satisfied_dict: Dict[str, ossp.Satisfied] = self._create_satisfied_dict()\n\n        if by_comp.export:\n            self._provided_dict = self._create_provided_dict()\n            self._responsibility_dict = self._create_responsibility_dict()\n            self._responsibility_by_provided = self._create_responsibility_by_provided_dict()\n\n    def _create_provided_dict(self) -> Dict[str, ossp.Provided]:\n        provided_dict: Dict[str, ossp.Provided] = {}\n        for provided in as_list(self._by_comp.export.provided):\n            provided_dict[provided.uuid] = provided\n        return provided_dict\n\n    def _create_responsibility_dict(self) -> Dict[str, ossp.Responsibility]:\n        responsibility_dict: Dict[str, ossp.Responsibility] = {}\n        for responsibility in as_list(self._by_comp.export.responsibilities):\n            responsibility_dict[responsibility.uuid] = responsibility\n        return responsibility_dict\n\n    def _create_responsibility_by_provided_dict(self) -> Dict[str, List[ossp.Responsibility]]:\n        responsibility_by_provided: Dict[str, List[ossp.Responsibility]] = {}\n        for responsibility in as_list(self._by_comp.export.responsibilities):\n            if responsibility.provided_uuid is None:\n                continue\n            if responsibility.provided_uuid not in responsibility_by_provided:\n                responsibility_by_provided[responsibility.provided_uuid] = [responsibility]\n            else:\n                existing_list: List[ossp.Responsibility] = responsibility_by_provided[responsibility.provided_uuid]\n                existing_list.append(responsibility)\n        return responsibility_by_provided\n\n    def _create_inherited_dict(self) -> Dict[str, ossp.Inherited]:\n        inherited_dict: Dict[str, ossp.Inherited] = {}\n        for inherited in as_list(self._by_comp.inherited):\n            inherited_dict[str(inherited.provided_uuid)] = inherited\n        return inherited_dict\n\n    def _create_satisfied_dict(self) -> Dict[str, ossp.Satisfied]:\n        satisfied_dict: Dict[str, ossp.Satisfied] = {}\n        for satisfied in as_list(self._by_comp.satisfied):\n            satisfied_dict[str(satisfied.responsibility_uuid)] = satisfied\n        return satisfied_dict\n\n    def get_isolated_responsibilities(self) -> List[ossp.Responsibility]:\n\"\"\"Return all isolated exported responsibilities.\"\"\"\n        all_responsibilities: List[ossp.Responsibility] = []\n        for resp in as_dict(self._responsibility_dict).values():\n            if resp.provided_uuid is None:\n                all_responsibilities.append(resp)\n        return all_responsibilities\n\n    def get_isolated_provided(self) -> List[ossp.Provided]:\n\"\"\"Return all isolated exported provided capabilities.\"\"\"\n        all_provided: List[ossp.Provided] = []\n        for provided in as_dict(self._provided_dict).values():\n            if not self._provided_has_responsibilities(provided.uuid):\n                all_provided.append(provided)\n        return all_provided\n\n    def get_export_sets(self) -> List[Tuple[ossp.Responsibility, ossp.Provided]]:\n\"\"\"Return a dictionary of every responsibility relationship with provided.\"\"\"\n        all_export_sets: List[Tuple[ossp.Responsibility, ossp.Provided]] = []\n        for provided_uuid, responsibilities in as_dict(self._responsibility_by_provided).items():\n\n            # Ensure the provided object exists in the dictionary.\n            # If it doesn't this is a bug.\n            if provided_uuid not in self._provided_dict:\n                raise TrestleError(f'Provided capability {provided_uuid} not found')\n            provided: ossp.Provided = self._provided_dict[provided_uuid]\n\n            for responsibility in responsibilities:\n                shared_responsibility: Tuple[ossp.Responsibility, ossp.Provided] = (responsibility, provided)\n                all_export_sets.append(shared_responsibility)\n        return all_export_sets\n\n    def reconcile_inheritance_by_component(\n        self, incoming_inherited: List[ossp.Inherited], incoming_satisfied: List[ossp.Satisfied]\n    ) -> ossp.ByComponent:\n\"\"\"\n        Reconcile the inherited and satisfied statements in the by-component assembly with changes from the export.\n\n        Notes:\n            A statement is determined as existing if the provided uuid or responsibility uuid is in the existing\n            by-component assembly. If existing, the description will be updated if it has changed.\n\n            Any existing inherited or satisfied statements that are not in the incoming export will be removed.\n            If a statement is in the incoming export, but not in the existing by-component assembly, it will be added.\n        \"\"\"\n        new_inherited: List[ossp.Inherited] = []\n        new_satisfied: List[ossp.Satisfied] = []\n\n        # Create a copy of the input by-component assembly to reconcile and return\n        new_by_comp: ossp.ByComponent = copy.deepcopy(self._by_comp)\n\n        for statement in incoming_inherited:\n            if statement.provided_uuid in self._inherited_dict:\n                existing_statement = self._inherited_dict[str(statement.provided_uuid)]\n                # Update the description if it has changed\n                existing_statement.description = statement.description\n                statement = existing_statement\n            new_inherited.append(statement)\n\n        new_by_comp.inherited = none_if_empty(new_inherited)\n\n        for statement in incoming_satisfied:\n            if statement.responsibility_uuid in self._satisfied_dict:\n                existing_statement = self._satisfied_dict[str(statement.responsibility_uuid)]\n                # Update the description if it has changed\n                existing_statement.description = statement.description\n                statement = existing_statement\n            new_satisfied.append(statement)\n\n        new_by_comp.satisfied = none_if_empty(new_satisfied)\n\n        return new_by_comp\n\n    def _provided_has_responsibilities(self, provided_uuid: str) -> bool:\n\"\"\"Return whether a provided UUID has responsibilities.\"\"\"\n        return provided_uuid in self._responsibility_by_provided\n
                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.__init__","title":"__init__(self, by_comp) special","text":"

                                                                            Initialize export writer for a single by-component assembly.

                                                                            Source code in trestle/core/crm/bycomp_interface.py
                                                                            def __init__(self, by_comp: ossp.ByComponent):\n\"\"\"Initialize export writer for a single by-component assembly.\"\"\"\n    self._by_comp: ossp.ByComponent = by_comp\n\n    self._provided_dict: Dict[str, ossp.Provided] = {}\n    self._responsibility_dict: Dict[str, ossp.Responsibility] = {}\n    self._responsibility_by_provided: Dict[str, List[ossp.Responsibility]] = {}\n\n    self._inherited_dict: Dict[str, ossp.Inherited] = self._create_inherited_dict()\n    self._satisfied_dict: Dict[str, ossp.Satisfied] = self._create_satisfied_dict()\n\n    if by_comp.export:\n        self._provided_dict = self._create_provided_dict()\n        self._responsibility_dict = self._create_responsibility_dict()\n        self._responsibility_by_provided = self._create_responsibility_by_provided_dict()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.get_export_sets","title":"get_export_sets(self)","text":"

                                                                            Return a dictionary of every responsibility relationship with provided.

                                                                            Source code in trestle/core/crm/bycomp_interface.py
                                                                            def get_export_sets(self) -> List[Tuple[ossp.Responsibility, ossp.Provided]]:\n\"\"\"Return a dictionary of every responsibility relationship with provided.\"\"\"\n    all_export_sets: List[Tuple[ossp.Responsibility, ossp.Provided]] = []\n    for provided_uuid, responsibilities in as_dict(self._responsibility_by_provided).items():\n\n        # Ensure the provided object exists in the dictionary.\n        # If it doesn't this is a bug.\n        if provided_uuid not in self._provided_dict:\n            raise TrestleError(f'Provided capability {provided_uuid} not found')\n        provided: ossp.Provided = self._provided_dict[provided_uuid]\n\n        for responsibility in responsibilities:\n            shared_responsibility: Tuple[ossp.Responsibility, ossp.Provided] = (responsibility, provided)\n            all_export_sets.append(shared_responsibility)\n    return all_export_sets\n
                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.get_isolated_provided","title":"get_isolated_provided(self)","text":"

                                                                            Return all isolated exported provided capabilities.

                                                                            Source code in trestle/core/crm/bycomp_interface.py
                                                                            def get_isolated_provided(self) -> List[ossp.Provided]:\n\"\"\"Return all isolated exported provided capabilities.\"\"\"\n    all_provided: List[ossp.Provided] = []\n    for provided in as_dict(self._provided_dict).values():\n        if not self._provided_has_responsibilities(provided.uuid):\n            all_provided.append(provided)\n    return all_provided\n
                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.get_isolated_responsibilities","title":"get_isolated_responsibilities(self)","text":"

                                                                            Return all isolated exported responsibilities.

                                                                            Source code in trestle/core/crm/bycomp_interface.py
                                                                            def get_isolated_responsibilities(self) -> List[ossp.Responsibility]:\n\"\"\"Return all isolated exported responsibilities.\"\"\"\n    all_responsibilities: List[ossp.Responsibility] = []\n    for resp in as_dict(self._responsibility_dict).values():\n        if resp.provided_uuid is None:\n            all_responsibilities.append(resp)\n    return all_responsibilities\n
                                                                            "},{"location":"api_reference/trestle.core.crm.bycomp_interface/#trestle.core.crm.bycomp_interface.ByComponentInterface.reconcile_inheritance_by_component","title":"reconcile_inheritance_by_component(self, incoming_inherited, incoming_satisfied)","text":"

                                                                            Reconcile the inherited and satisfied statements in the by-component assembly with changes from the export.

                                                                            Notes

                                                                            A statement is determined as existing if the provided uuid or responsibility uuid is in the existing by-component assembly. If existing, the description will be updated if it has changed.

                                                                            Any existing inherited or satisfied statements that are not in the incoming export will be removed. If a statement is in the incoming export, but not in the existing by-component assembly, it will be added.

                                                                            Source code in trestle/core/crm/bycomp_interface.py
                                                                            def reconcile_inheritance_by_component(\n    self, incoming_inherited: List[ossp.Inherited], incoming_satisfied: List[ossp.Satisfied]\n) -> ossp.ByComponent:\n\"\"\"\n    Reconcile the inherited and satisfied statements in the by-component assembly with changes from the export.\n\n    Notes:\n        A statement is determined as existing if the provided uuid or responsibility uuid is in the existing\n        by-component assembly. If existing, the description will be updated if it has changed.\n\n        Any existing inherited or satisfied statements that are not in the incoming export will be removed.\n        If a statement is in the incoming export, but not in the existing by-component assembly, it will be added.\n    \"\"\"\n    new_inherited: List[ossp.Inherited] = []\n    new_satisfied: List[ossp.Satisfied] = []\n\n    # Create a copy of the input by-component assembly to reconcile and return\n    new_by_comp: ossp.ByComponent = copy.deepcopy(self._by_comp)\n\n    for statement in incoming_inherited:\n        if statement.provided_uuid in self._inherited_dict:\n            existing_statement = self._inherited_dict[str(statement.provided_uuid)]\n            # Update the description if it has changed\n            existing_statement.description = statement.description\n            statement = existing_statement\n        new_inherited.append(statement)\n\n    new_by_comp.inherited = none_if_empty(new_inherited)\n\n    for statement in incoming_satisfied:\n        if statement.responsibility_uuid in self._satisfied_dict:\n            existing_statement = self._satisfied_dict[str(statement.responsibility_uuid)]\n            # Update the description if it has changed\n            existing_statement.description = statement.description\n            statement = existing_statement\n        new_satisfied.append(statement)\n\n    new_by_comp.satisfied = none_if_empty(new_satisfied)\n\n    return new_by_comp\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_reader/","title":"export_reader","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader","title":"trestle.core.crm.export_reader","text":"

                                                                            Provided interface to read inheritance statements from Markdown.

                                                                            "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ByComponentDict","title":"ByComponentDict","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.InheritanceViewDict","title":"InheritanceViewDict","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader","title":" ExportReader ","text":"

                                                                            By-Component Assembly Exports Markdown reader.

                                                                            Export reader handles all operations related to reading authored inherited and satisfied statements from exports in Markdown. The reader will read all the markdown files in the exports directory and update the SSP with the inheritance.

                                                                            Source code in trestle/core/crm/export_reader.py
                                                                            class ExportReader:\n\"\"\"\n    By-Component Assembly Exports Markdown reader.\n\n    Export reader handles all operations related to reading authored inherited and satisfied statements from exports\n    in Markdown. The reader will read all the markdown files in the exports directory and update the SSP with the\n    inheritance.\n    \"\"\"\n\n    def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan):\n\"\"\"\n        Initialize export reader.\n\n        Arguments:\n            root_path: A root path object where an SSP's inheritance markdown is located.\n            ssp: A system security plan object that will be updated with the inheritance information.\n\n        Notes:\n            The mapped components list is used to track which components have been mapped to controls in the markdown.\n            It can be retrieved with the get_leveraged_components method. This will be empty until the\n            read_exports_from_markdown method is called.\n        \"\"\"\n        self._ssp: ossp.SystemSecurityPlan = ssp\n\n        # Create a dictionary of implemented requirements keyed by control id for merging operations\n        self._implemented_requirements: Dict[str, ossp.ImplementedRequirement] = self._create_impl_req_dict()\n\n        # List of component titles that have been mapped to controls in the Markdown\n        self._mapped_components: List[str] = []\n\n        self._root_path: pathlib.Path = root_path\n\n    def _create_impl_req_dict(self) -> Dict[str, ossp.ImplementedRequirement]:\n\"\"\"Create a dictionary of implemented requirements keyed by control id.\"\"\"\n        impl_req_dict: Dict[str, ossp.ImplementedRequirement] = {}\n        for impl_req in as_list(self._ssp.control_implementation.implemented_requirements):\n            impl_req_dict[impl_req.control_id] = impl_req\n        return impl_req_dict\n\n    def read_exports_from_markdown(self) -> ossp.SystemSecurityPlan:\n\"\"\"Read inheritance markdown and update the SSP with the inheritance information.\"\"\"\n        # Read the information from the markdown files into a dictionary for quick lookup\n        markdown_dict: InheritanceViewDict = self._read_inheritance_markdown_directory()\n\n        # Merge the markdown information into existing the implemented requirements\n        self._merge_exports_implemented_requirements(markdown_dict)\n\n        # Process remaining markdown information that was not in the implemented requirements\n        for control_id, by_comp_dict in markdown_dict.items():\n            if by_comp_dict:\n                logging.debug(f'Adding control mapping {control_id} to implemented requirements')\n                self._add_control_mappings_to_implemented_requirements(control_id, by_comp_dict)\n\n        self._ssp.control_implementation.implemented_requirements = list(self._implemented_requirements.values())\n        return self._ssp\n\n    def get_leveraged_ssp_href(self) -> str:\n\"\"\"Get the href of the leveraged SSP from a markdown file.\"\"\"\n        comp_dirs = os.listdir(self._root_path)\n        if len(comp_dirs) == 0:\n            raise TrestleError('No components were found in the markdown.')\n\n        control_dirs = os.listdir(self._root_path.joinpath(comp_dirs[0]))\n        if len(control_dirs) == 0:\n            raise TrestleError('No controls were found in the markdown for component {comp_dirs[0]}.')\n\n        control_dir = self._root_path.joinpath(comp_dirs[0], control_dirs[0])\n\n        files = [f for f in os.listdir(control_dir) if os.path.isfile(os.path.join(control_dir, f))]\n        if len(files) == 0:\n            raise TrestleError(f'No files were found in the markdown for control {control_dirs[0]}.')\n\n        markdown_file_path = control_dir.joinpath(files[0])\n        reader = InheritanceMarkdownReader(markdown_file_path)\n        return reader.get_leveraged_ssp_reference()\n\n    def get_leveraged_components(self) -> List[str]:\n\"\"\"Get a list of component titles that have been mapped to controls in the Markdown.\"\"\"\n        return self._mapped_components\n\n    def _merge_exports_implemented_requirements(self, markdown_dict: InheritanceViewDict) -> None:\n\"\"\"Merge all exported inheritance info from the markdown into the implemented requirement dict.\"\"\"\n        for implemented_requirement in self._implemented_requirements.values():\n\n            # If the control id existing in the markdown, then update the by_components\n            if implemented_requirement.control_id in markdown_dict:\n\n                # Delete the entry from the markdown_dict once processed to avoid duplicates\n                by_comp_dict: ByComponentDict = markdown_dict.pop(implemented_requirement.control_id)\n\n                self._update_type_with_by_comp(implemented_requirement, by_comp_dict)\n\n            # Update any implemented requirements statements assemblies\n            new_statements: List[ossp.Statement] = []\n\n            for stm in as_list(implemented_requirement.statements):\n                statement_id = getattr(stm, 'statement_id', f'{implemented_requirement.control_id}_smt')\n\n                # If the statement id existing in the markdown, then update the by_components\n                if statement_id in markdown_dict:\n\n                    # Delete the entry from the markdown_dict once processed to avoid duplicates\n                    by_comp_dict: ByComponentDict = markdown_dict.pop(statement_id)\n\n                    self._update_type_with_by_comp(stm, by_comp_dict)\n\n                new_statements.append(stm)\n\n            implemented_requirement.statements = none_if_empty(new_statements)\n\n    def _update_type_with_by_comp(self, with_bycomp: TypeWithByComps, by_comp_dict: ByComponentDict) -> None:\n\"\"\"Update the by_components for a type with by_components.\"\"\"\n        new_by_comp: List[ossp.ByComponent] = []\n\n        by_comp: ossp.ByComponent\n        comp_inheritance_info: Tuple[List[ossp.Inherited], List[ossp.Satisfied]]\n        for by_comp in as_list(with_bycomp.by_components):\n\n            # If the by_component uuid exists in the by_comp_dict, then update it\n            # If not, clear the by_component inheritance information\n            comp_inheritance_info = by_comp_dict.pop(by_comp.component_uuid, ([], []))\n\n            bycomp_interface = ByComponentInterface(by_comp)\n            by_comp = bycomp_interface.reconcile_inheritance_by_component(\n                comp_inheritance_info[0], comp_inheritance_info[1]\n            )\n\n            new_by_comp.append(by_comp)\n\n        # Add any new by_components that were not in the original statement\n        new_by_comp.extend(ExportReader._add_new_by_comps(by_comp_dict))\n        with_bycomp.by_components = none_if_empty(new_by_comp)\n\n    def _add_control_mappings_to_implemented_requirements(\n        self, control_mapping: str, by_comps: ByComponentDict\n    ) -> None:\n\"\"\"Add control mappings to implemented requirements.\"\"\"\n        # Determine if the control id is actually a statement id\n        if '_smt.' in control_mapping:\n            control_id = control_mapping.split('_smt')[0]\n            implemented_req = self._add_or_get_implemented_requirement(control_id)\n            statement = gens.generate_sample_model(ossp.Statement)\n            statement.statement_id = control_mapping\n            statement.by_components = ExportReader._add_new_by_comps(by_comps)\n            implemented_req.statements = as_list(implemented_req.statements)\n            implemented_req.statements.append(statement)\n            implemented_req.statements = sorted(implemented_req.statements, key=lambda x: x.statement_id)\n        else:\n            implemented_req = self._add_or_get_implemented_requirement(control_mapping)\n            implemented_req.by_components = as_list(implemented_req.by_components)\n            implemented_req.by_components.extend(ExportReader._add_new_by_comps(by_comps))\n\n    def _add_or_get_implemented_requirement(self, control_id: str) -> ossp.ImplementedRequirement:\n\"\"\"Add or get implemented requirement from implemented requirements dictionary.\"\"\"\n        if control_id in self._implemented_requirements:\n            return self._implemented_requirements[control_id]\n\n        implemented_requirement = gens.generate_sample_model(ossp.ImplementedRequirement)\n        implemented_requirement.control_id = control_id\n        self._implemented_requirements[control_id] = implemented_requirement\n        return implemented_requirement\n\n    @staticmethod\n    def _add_new_by_comps(by_comp_dict: ByComponentDict) -> List[ossp.ByComponent]:\n\"\"\"Add new by_components to the implemented requirement.\"\"\"\n        new_by_comp: List[ossp.ByComponent] = []\n        for comp_uuid, inheritance_info in by_comp_dict.items():\n            by_comp: ossp.ByComponent = gens.generate_sample_model(ossp.ByComponent)\n            by_comp.component_uuid = comp_uuid\n            by_comp.inherited = none_if_empty(inheritance_info[0])\n            by_comp.satisfied = none_if_empty(inheritance_info[1])\n            new_by_comp.append(by_comp)\n        return new_by_comp\n\n    def _read_inheritance_markdown_directory(self) -> InheritanceViewDict:\n\"\"\"Read all inheritance markdown files and return a dictionary of all the information.\"\"\"\n        markdown_dict: InheritanceViewDict = {}\n\n        # Creating a dictionary to find the component uuid by title for faster lookup\n        uuid_by_title: Dict[str, str] = {}\n        for component in as_list(self._ssp.system_implementation.components):\n            uuid_by_title[component.title] = component.uuid\n\n        for comp_dir in os.listdir(self._root_path):\n            is_comp_leveraged = False\n            for control_dir in os.listdir(os.path.join(self._root_path, comp_dir)):\n                control_dir_path = os.path.join(self._root_path, comp_dir, control_dir)\n\n                # Initialize the by_component dictionary for the control directory\n                # If it exists in the markdown dictionary, then update it with the new information\n                by_comp_dict = markdown_dict.get(control_dir, {})\n\n                for file in os.listdir(control_dir_path):\n                    file_path = pathlib.Path(control_dir_path).joinpath(file)\n                    reader = InheritanceMarkdownReader(file_path)\n                    leveraged_info = reader.process_leveraged_statement_markdown()\n\n                    # If there is no leveraged information, then skip this file\n                    if leveraged_info is None:\n                        continue\n\n                    # If a file has leveraged information, then set the flag to indicate the component is leveraged\n                    is_comp_leveraged = True\n\n                    for comp in leveraged_info.leveraging_comp_titles:\n                        if comp not in uuid_by_title:\n                            keys_as_string = ', '.join(uuid_by_title.keys())\n                            raise TrestleError(\n                                f'Component \"{comp}\" does not exist in the {self._ssp.metadata.title} SSP. '\n                                f'Please use options: {keys_as_string}.'\n                            )\n\n                        comp_uuid = uuid_by_title[comp]\n                        inherited, satisfied = by_comp_dict.get(comp_uuid, ([], []))\n\n                        if leveraged_info.inherited is not None:\n                            inherited.append(leveraged_info.inherited)\n                        if leveraged_info.satisfied is not None:\n                            satisfied.append(leveraged_info.satisfied)\n\n                        by_comp_dict[comp_uuid] = (inherited, satisfied)\n\n                markdown_dict[control_dir] = by_comp_dict\n\n            if is_comp_leveraged:\n                self._mapped_components.append(comp_dir)\n\n        return markdown_dict\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.__init__","title":"__init__(self, root_path, ssp) special","text":"

                                                                            Initialize export reader.

                                                                            Parameters:

                                                                            Name Type Description Default root_path Path

                                                                            A root path object where an SSP's inheritance markdown is located.

                                                                            required ssp SystemSecurityPlan

                                                                            A system security plan object that will be updated with the inheritance information.

                                                                            required

                                                                            Notes

                                                                            The mapped components list is used to track which components have been mapped to controls in the markdown. It can be retrieved with the get_leveraged_components method. This will be empty until the read_exports_from_markdown method is called.

                                                                            Source code in trestle/core/crm/export_reader.py
                                                                            def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan):\n\"\"\"\n    Initialize export reader.\n\n    Arguments:\n        root_path: A root path object where an SSP's inheritance markdown is located.\n        ssp: A system security plan object that will be updated with the inheritance information.\n\n    Notes:\n        The mapped components list is used to track which components have been mapped to controls in the markdown.\n        It can be retrieved with the get_leveraged_components method. This will be empty until the\n        read_exports_from_markdown method is called.\n    \"\"\"\n    self._ssp: ossp.SystemSecurityPlan = ssp\n\n    # Create a dictionary of implemented requirements keyed by control id for merging operations\n    self._implemented_requirements: Dict[str, ossp.ImplementedRequirement] = self._create_impl_req_dict()\n\n    # List of component titles that have been mapped to controls in the Markdown\n    self._mapped_components: List[str] = []\n\n    self._root_path: pathlib.Path = root_path\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.get_leveraged_components","title":"get_leveraged_components(self)","text":"

                                                                            Get a list of component titles that have been mapped to controls in the Markdown.

                                                                            Source code in trestle/core/crm/export_reader.py
                                                                            def get_leveraged_components(self) -> List[str]:\n\"\"\"Get a list of component titles that have been mapped to controls in the Markdown.\"\"\"\n    return self._mapped_components\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.get_leveraged_ssp_href","title":"get_leveraged_ssp_href(self)","text":"

                                                                            Get the href of the leveraged SSP from a markdown file.

                                                                            Source code in trestle/core/crm/export_reader.py
                                                                            def get_leveraged_ssp_href(self) -> str:\n\"\"\"Get the href of the leveraged SSP from a markdown file.\"\"\"\n    comp_dirs = os.listdir(self._root_path)\n    if len(comp_dirs) == 0:\n        raise TrestleError('No components were found in the markdown.')\n\n    control_dirs = os.listdir(self._root_path.joinpath(comp_dirs[0]))\n    if len(control_dirs) == 0:\n        raise TrestleError('No controls were found in the markdown for component {comp_dirs[0]}.')\n\n    control_dir = self._root_path.joinpath(comp_dirs[0], control_dirs[0])\n\n    files = [f for f in os.listdir(control_dir) if os.path.isfile(os.path.join(control_dir, f))]\n    if len(files) == 0:\n        raise TrestleError(f'No files were found in the markdown for control {control_dirs[0]}.')\n\n    markdown_file_path = control_dir.joinpath(files[0])\n    reader = InheritanceMarkdownReader(markdown_file_path)\n    return reader.get_leveraged_ssp_reference()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_reader/#trestle.core.crm.export_reader.ExportReader.read_exports_from_markdown","title":"read_exports_from_markdown(self)","text":"

                                                                            Read inheritance markdown and update the SSP with the inheritance information.

                                                                            Source code in trestle/core/crm/export_reader.py
                                                                            def read_exports_from_markdown(self) -> ossp.SystemSecurityPlan:\n\"\"\"Read inheritance markdown and update the SSP with the inheritance information.\"\"\"\n    # Read the information from the markdown files into a dictionary for quick lookup\n    markdown_dict: InheritanceViewDict = self._read_inheritance_markdown_directory()\n\n    # Merge the markdown information into existing the implemented requirements\n    self._merge_exports_implemented_requirements(markdown_dict)\n\n    # Process remaining markdown information that was not in the implemented requirements\n    for control_id, by_comp_dict in markdown_dict.items():\n        if by_comp_dict:\n            logging.debug(f'Adding control mapping {control_id} to implemented requirements')\n            self._add_control_mappings_to_implemented_requirements(control_id, by_comp_dict)\n\n    self._ssp.control_implementation.implemented_requirements = list(self._implemented_requirements.values())\n    return self._ssp\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_writer/","title":"export_writer","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer","title":"trestle.core.crm.export_writer","text":"

                                                                            Provided interface to write provided and responsibility exports statements to Markdown.

                                                                            "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter","title":" ExportWriter ","text":"

                                                                            By-Component Assembly Exports writer.

                                                                            Export writer handles all operations related to writing provided and responsibility exported statements to Markdown.

                                                                            Source code in trestle/core/crm/export_writer.py
                                                                            class ExportWriter:\n\"\"\"\n    By-Component Assembly Exports writer.\n\n    Export writer handles all operations related to writing provided and responsibility exported statements\n    to Markdown.\n    \"\"\"\n\n    def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan, leveraged_ssp_href: str):\n\"\"\"\n        Initialize export writer.\n\n        Arguments:\n            root_path: A root path object where all markdown files and directories should be written.\n            ssp: A system security plan with exports\n        \"\"\"\n        self._ssp: ossp.SystemSecurityPlan = ssp\n        self._root_path: pathlib.Path = root_path\n        self._leveraged_ssp_href: str = leveraged_ssp_href\n\n        # Find all the components and create paths for name\n        self._paths_by_comp: Dict[str, pathlib.Path] = {}\n        for component in as_list(self._ssp.system_implementation.components):\n            self._paths_by_comp[component.uuid] = self._root_path.joinpath(component.title)\n\n    def write_exports_as_markdown(self) -> None:\n\"\"\"Write export statement for leveraged SSP as the inheritance Markdown view.\"\"\"\n        # Process all information under exports in control implementation\n        for implemented_requirement in as_list(self._ssp.control_implementation.implemented_requirements):\n            for by_comp in as_list(implemented_requirement.by_components):\n                self._process_by_component(by_comp, implemented_requirement.control_id)\n\n            for stm in as_list(implemented_requirement.statements):\n                statement_id = getattr(stm, 'statement_id', f'{implemented_requirement.control_id}_smt')\n                for by_comp in as_list(stm.by_components):\n                    self._process_by_component(by_comp, statement_id)\n\n    def _process_by_component(self, by_comp: ossp.ByComponent, control_id: str) -> None:\n\"\"\"Complete the Markdown writing operations for each by-component assembly.\"\"\"\n        if by_comp.component_uuid not in self._paths_by_comp:\n            raise TrestleError(f'Component id {by_comp.component_uuid} is not in the system implementation')\n\n        comp_path: pathlib.Path = self._paths_by_comp[by_comp.component_uuid]\n\n        export_interface: ByComponentInterface = ByComponentInterface(by_comp=by_comp)\n        leveraged_statements: Dict[str, LeveragedStatements] = self._statement_types_from_exports(export_interface)\n\n        # Only create the directory if leveraged statements exist. If not return.\n        if not leveraged_statements:\n            logger.debug(f'Component {by_comp.component_uuid} has no exports for control {control_id}')\n            return\n\n        control_path: pathlib.Path = comp_path.joinpath(control_id)\n        control_path.mkdir(exist_ok=True, parents=True)\n\n        for statement_file_path, leveraged_stm in leveraged_statements.items():\n            statement_path: pathlib.Path = control_path.joinpath(f'{statement_file_path}{const.MARKDOWN_FILE_EXT}')\n            leveraged_stm.write_statement_md(statement_path)\n\n    def _statement_types_from_exports(self, export_interface: ByComponentInterface) -> Dict[str, LeveragedStatements]:\n\"\"\"Process all exports and return a file basename and LeveragedStatement object for each.\"\"\"\n        all_statements: Dict[str, LeveragedStatements] = {}\n\n        for responsibility in export_interface.get_isolated_responsibilities():\n            all_statements[responsibility.uuid] = StatementResponsibility(\n                responsibility.uuid, responsibility.description, self._leveraged_ssp_href\n            )\n\n        for provided in export_interface.get_isolated_provided():\n            all_statements[provided.uuid\n                           ] = StatementProvided(provided.uuid, provided.description, self._leveraged_ssp_href)\n\n        for responsibility, provided in export_interface.get_export_sets():\n            path = f'{provided.uuid}_{responsibility.uuid}'\n            all_statements[path] = StatementTree(\n                provided.uuid,\n                provided.description,\n                responsibility.uuid,\n                responsibility.description,\n                self._leveraged_ssp_href\n            )\n\n        return all_statements\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter.__init__","title":"__init__(self, root_path, ssp, leveraged_ssp_href) special","text":"

                                                                            Initialize export writer.

                                                                            Parameters:

                                                                            Name Type Description Default root_path Path

                                                                            A root path object where all markdown files and directories should be written.

                                                                            required ssp SystemSecurityPlan

                                                                            A system security plan with exports

                                                                            required Source code in trestle/core/crm/export_writer.py
                                                                            def __init__(self, root_path: pathlib.Path, ssp: ossp.SystemSecurityPlan, leveraged_ssp_href: str):\n\"\"\"\n    Initialize export writer.\n\n    Arguments:\n        root_path: A root path object where all markdown files and directories should be written.\n        ssp: A system security plan with exports\n    \"\"\"\n    self._ssp: ossp.SystemSecurityPlan = ssp\n    self._root_path: pathlib.Path = root_path\n    self._leveraged_ssp_href: str = leveraged_ssp_href\n\n    # Find all the components and create paths for name\n    self._paths_by_comp: Dict[str, pathlib.Path] = {}\n    for component in as_list(self._ssp.system_implementation.components):\n        self._paths_by_comp[component.uuid] = self._root_path.joinpath(component.title)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.export_writer/#trestle.core.crm.export_writer.ExportWriter.write_exports_as_markdown","title":"write_exports_as_markdown(self)","text":"

                                                                            Write export statement for leveraged SSP as the inheritance Markdown view.

                                                                            Source code in trestle/core/crm/export_writer.py
                                                                            def write_exports_as_markdown(self) -> None:\n\"\"\"Write export statement for leveraged SSP as the inheritance Markdown view.\"\"\"\n    # Process all information under exports in control implementation\n    for implemented_requirement in as_list(self._ssp.control_implementation.implemented_requirements):\n        for by_comp in as_list(implemented_requirement.by_components):\n            self._process_by_component(by_comp, implemented_requirement.control_id)\n\n        for stm in as_list(implemented_requirement.statements):\n            statement_id = getattr(stm, 'statement_id', f'{implemented_requirement.control_id}_smt')\n            for by_comp in as_list(stm.by_components):\n                self._process_by_component(by_comp, statement_id)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/","title":"leveraged_statements","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements","title":"trestle.core.crm.leveraged_statements","text":"

                                                                            Handle writing of inherited statements to markdown.

                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.component_mapping_default","title":"component_mapping_default: List[Dict[str, str]]","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo","title":" InheritanceInfo dataclass","text":"

                                                                            Class to capture component inheritance information.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            @dataclass\nclass InheritanceInfo:\n\"\"\"Class to capture component inheritance information.\"\"\"\n\n    leveraging_comp_titles: List[str]\n    inherited: Optional[ssp.Inherited]\n    satisfied: Optional[ssp.Satisfied]\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.inherited","title":"inherited: Optional[trestle.oscal.ssp.Inherited] dataclass-field","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.leveraging_comp_titles","title":"leveraging_comp_titles: List[str] dataclass-field","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.satisfied","title":"satisfied: Optional[trestle.oscal.ssp.Satisfied] dataclass-field","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.__eq__","title":"__eq__(self, other) special","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.__init__","title":"__init__(self, leveraging_comp_titles, inherited, satisfied) special","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceInfo.__repr__","title":"__repr__(self) special","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader","title":" InheritanceMarkdownReader ","text":"

                                                                            Class to read leveraged statement information from Markdown.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            class InheritanceMarkdownReader:\n\"\"\"Class to read leveraged statement information from Markdown.\"\"\"\n\n    def __init__(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n        # Save the file name for logging\n        self._leveraged_statement_file = leveraged_statement_file\n\n        md_api: MarkdownAPI = MarkdownAPI()\n\n        yaml_header, inheritance_md = md_api.processor.process_markdown(leveraged_statement_file)\n        self._yaml_header: Dict[str, Any] = yaml_header\n        self._inheritance_md: DocsMarkdownNode = inheritance_md\n\n    def process_leveraged_statement_markdown(self) -> Optional[InheritanceInfo]:\n\"\"\"\n        Read inheritance information from Markdown.\n\n        Returns:\n            Optional InheritanceInfo - A list of mapped component titles, an optional satisfied statement and an\n            optional inherited statement\n\n        Notes:\n            Returns inheritance information in the context of the leveraging SSP. If no leveraging component titles are\n            mapped in the yaml header None will be returned. The satisfied and inherited fields are\n            generated and returned to added information to by-component assemblies for\n            the mapped leveraging components.\n\n        \"\"\"\n        leveraging_comps: List[str] = []\n        inherited_statement: Optional[ssp.Inherited] = None\n        satisfied_statement: Optional[ssp.Satisfied] = None\n\n        leveraging_comp_header_value: List[Dict[str, str]] = self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n\n        # If there are no mapped components, return early\n        if not leveraging_comp_header_value or leveraging_comp_header_value == component_mapping_default:\n            return None\n        else:\n            for comp_dicts in leveraging_comp_header_value:\n                for comp_title in comp_dicts.values():\n                    leveraging_comps.append(comp_title)\n\n        statement_info: Dict[str, str] = self._yaml_header[const.TRESTLE_STATEMENT_TAG]\n\n        if const.PROVIDED_UUID in statement_info:\n            # Set inherited\n\n            provided_description = self.get_provided_description()\n            if provided_description is None:\n                raise TrestleError(f'Provided statement cannot be empty in {self._leveraged_statement_file}')\n\n            inherited_statement = gens.generate_sample_model(ssp.Inherited)\n\n            inherited_statement.description = provided_description\n            inherited_statement.provided_uuid = statement_info[const.PROVIDED_UUID]\n\n        if const.RESPONSIBILITY_UUID in statement_info:\n            # Set satisfied\n            satisfied_description = self.get_satisfied_description()\n            if satisfied_description is None:\n                raise TrestleError(f'Satisfied statement cannot be empty in {self._leveraged_statement_file}')\n\n            satisfied_statement = gens.generate_sample_model(ssp.Satisfied)\n\n            satisfied_statement.description = satisfied_description\n            satisfied_statement.responsibility_uuid = statement_info[const.RESPONSIBILITY_UUID]\n\n        return InheritanceInfo(leveraging_comps, inherited_statement, satisfied_statement)\n\n    def get_leveraged_ssp_reference(self) -> str:\n\"\"\"Return the leveraged SSP reference in the yaml header.\"\"\"\n        return self._yaml_header[const.TRESTLE_GLOBAL_TAG][const.LEVERAGED_SSP][const.HREF]\n\n    def get_satisfied_description(self) -> Optional[str]:\n\"\"\"Return the satisfied description in the Markdown.\"\"\"\n        node = self._inheritance_md.get_node_for_key(const.SATISFIED_STATEMENT_DESCRIPTION, False)\n        if node is not None:\n            return self.strip_heading_and_comments(node.content.raw_text)\n        else:\n            return None\n\n    def get_provided_description(self) -> Optional[str]:\n\"\"\"Return the provided description in the Markdown.\"\"\"\n        node = self._inheritance_md.get_node_for_key(const.PROVIDED_STATEMENT_DESCRIPTION, False)\n        if node is not None:\n            return self.strip_heading_and_comments(node.content.raw_text)\n        else:\n            return None\n\n    def get_leveraged_component_header_value(self) -> Dict[str, str]:\n\"\"\"Provide the leveraged component value in the yaml header.\"\"\"\n        return self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n\n    @staticmethod\n    def strip_heading_and_comments(markdown_text: str) -> str:\n\"\"\"Remove the heading and comments from lines to get the multi-line paragraph.\"\"\"\n        lines = markdown_text.split('\\n')\n        non_heading_comment_lines = []\n        inside_heading = False\n        inside_comment = False\n\n        for line in lines:\n            if line.startswith('#'):\n                inside_heading = True\n            elif line.startswith('<!--'):\n                inside_comment = True\n                if line.rstrip().endswith('-->'):\n                    inside_comment = False\n                continue\n            elif line.strip() == '':\n                inside_heading = False\n                inside_comment = False\n\n            if not inside_heading and not inside_comment:\n                non_heading_comment_lines.append(line)\n\n        stripped_markdown = '\\n'.join(non_heading_comment_lines).strip()\n        return stripped_markdown\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.__init__","title":"__init__(self, leveraged_statement_file) special","text":"

                                                                            Initialize the class.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def __init__(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n    # Save the file name for logging\n    self._leveraged_statement_file = leveraged_statement_file\n\n    md_api: MarkdownAPI = MarkdownAPI()\n\n    yaml_header, inheritance_md = md_api.processor.process_markdown(leveraged_statement_file)\n    self._yaml_header: Dict[str, Any] = yaml_header\n    self._inheritance_md: DocsMarkdownNode = inheritance_md\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_leveraged_component_header_value","title":"get_leveraged_component_header_value(self)","text":"

                                                                            Provide the leveraged component value in the yaml header.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def get_leveraged_component_header_value(self) -> Dict[str, str]:\n\"\"\"Provide the leveraged component value in the yaml header.\"\"\"\n    return self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_leveraged_ssp_reference","title":"get_leveraged_ssp_reference(self)","text":"

                                                                            Return the leveraged SSP reference in the yaml header.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def get_leveraged_ssp_reference(self) -> str:\n\"\"\"Return the leveraged SSP reference in the yaml header.\"\"\"\n    return self._yaml_header[const.TRESTLE_GLOBAL_TAG][const.LEVERAGED_SSP][const.HREF]\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_provided_description","title":"get_provided_description(self)","text":"

                                                                            Return the provided description in the Markdown.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def get_provided_description(self) -> Optional[str]:\n\"\"\"Return the provided description in the Markdown.\"\"\"\n    node = self._inheritance_md.get_node_for_key(const.PROVIDED_STATEMENT_DESCRIPTION, False)\n    if node is not None:\n        return self.strip_heading_and_comments(node.content.raw_text)\n    else:\n        return None\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.get_satisfied_description","title":"get_satisfied_description(self)","text":"

                                                                            Return the satisfied description in the Markdown.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def get_satisfied_description(self) -> Optional[str]:\n\"\"\"Return the satisfied description in the Markdown.\"\"\"\n    node = self._inheritance_md.get_node_for_key(const.SATISFIED_STATEMENT_DESCRIPTION, False)\n    if node is not None:\n        return self.strip_heading_and_comments(node.content.raw_text)\n    else:\n        return None\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.process_leveraged_statement_markdown","title":"process_leveraged_statement_markdown(self)","text":"

                                                                            Read inheritance information from Markdown.

                                                                            Returns:

                                                                            Type Description Optional[trestle.core.crm.leveraged_statements.InheritanceInfo]

                                                                            Optional InheritanceInfo - A list of mapped component titles, an optional satisfied statement and an optional inherited statement

                                                                            Notes

                                                                            Returns inheritance information in the context of the leveraging SSP. If no leveraging component titles are mapped in the yaml header None will be returned. The satisfied and inherited fields are generated and returned to added information to by-component assemblies for the mapped leveraging components.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def process_leveraged_statement_markdown(self) -> Optional[InheritanceInfo]:\n\"\"\"\n    Read inheritance information from Markdown.\n\n    Returns:\n        Optional InheritanceInfo - A list of mapped component titles, an optional satisfied statement and an\n        optional inherited statement\n\n    Notes:\n        Returns inheritance information in the context of the leveraging SSP. If no leveraging component titles are\n        mapped in the yaml header None will be returned. The satisfied and inherited fields are\n        generated and returned to added information to by-component assemblies for\n        the mapped leveraging components.\n\n    \"\"\"\n    leveraging_comps: List[str] = []\n    inherited_statement: Optional[ssp.Inherited] = None\n    satisfied_statement: Optional[ssp.Satisfied] = None\n\n    leveraging_comp_header_value: List[Dict[str, str]] = self._yaml_header[const.TRESTLE_LEVERAGING_COMP_TAG]\n\n    # If there are no mapped components, return early\n    if not leveraging_comp_header_value or leveraging_comp_header_value == component_mapping_default:\n        return None\n    else:\n        for comp_dicts in leveraging_comp_header_value:\n            for comp_title in comp_dicts.values():\n                leveraging_comps.append(comp_title)\n\n    statement_info: Dict[str, str] = self._yaml_header[const.TRESTLE_STATEMENT_TAG]\n\n    if const.PROVIDED_UUID in statement_info:\n        # Set inherited\n\n        provided_description = self.get_provided_description()\n        if provided_description is None:\n            raise TrestleError(f'Provided statement cannot be empty in {self._leveraged_statement_file}')\n\n        inherited_statement = gens.generate_sample_model(ssp.Inherited)\n\n        inherited_statement.description = provided_description\n        inherited_statement.provided_uuid = statement_info[const.PROVIDED_UUID]\n\n    if const.RESPONSIBILITY_UUID in statement_info:\n        # Set satisfied\n        satisfied_description = self.get_satisfied_description()\n        if satisfied_description is None:\n            raise TrestleError(f'Satisfied statement cannot be empty in {self._leveraged_statement_file}')\n\n        satisfied_statement = gens.generate_sample_model(ssp.Satisfied)\n\n        satisfied_statement.description = satisfied_description\n        satisfied_statement.responsibility_uuid = statement_info[const.RESPONSIBILITY_UUID]\n\n    return InheritanceInfo(leveraging_comps, inherited_statement, satisfied_statement)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.InheritanceMarkdownReader.strip_heading_and_comments","title":"strip_heading_and_comments(markdown_text) staticmethod","text":"

                                                                            Remove the heading and comments from lines to get the multi-line paragraph.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            @staticmethod\ndef strip_heading_and_comments(markdown_text: str) -> str:\n\"\"\"Remove the heading and comments from lines to get the multi-line paragraph.\"\"\"\n    lines = markdown_text.split('\\n')\n    non_heading_comment_lines = []\n    inside_heading = False\n    inside_comment = False\n\n    for line in lines:\n        if line.startswith('#'):\n            inside_heading = True\n        elif line.startswith('<!--'):\n            inside_comment = True\n            if line.rstrip().endswith('-->'):\n                inside_comment = False\n            continue\n        elif line.strip() == '':\n            inside_heading = False\n            inside_comment = False\n\n        if not inside_heading and not inside_comment:\n            non_heading_comment_lines.append(line)\n\n    stripped_markdown = '\\n'.join(non_heading_comment_lines).strip()\n    return stripped_markdown\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements","title":" LeveragedStatements (ABC) ","text":"

                                                                            Abstract class for managing leveraged statements.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            class LeveragedStatements(ABC):\n\"\"\"Abstract class for managing leveraged statements.\"\"\"\n\n    def __init__(self, leveraged_ssp_reference: str) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self._md_file: Optional[MDWriter] = None\n        self.header_comment_dict: Dict[str, str] = {\n            const.TRESTLE_LEVERAGING_COMP_TAG: const.YAML_LEVERAGING_COMP_COMMENT,\n            const.TRESTLE_STATEMENT_TAG: const.YAML_LEVERAGED_COMMENT\n        }\n        self.merged_header_dict: Dict[str, Any] = {\n            const.TRESTLE_STATEMENT_TAG: '',\n            const.TRESTLE_LEVERAGING_COMP_TAG: component_mapping_default,\n            const.TRESTLE_GLOBAL_TAG: {\n                const.LEVERAGED_SSP: {\n                    const.HREF: leveraged_ssp_reference\n                }\n            }\n        }\n\n    @abstractmethod\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write inheritance information to a single markdown file.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements.__init__","title":"__init__(self, leveraged_ssp_reference) special","text":"

                                                                            Initialize the class.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def __init__(self, leveraged_ssp_reference: str) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self._md_file: Optional[MDWriter] = None\n    self.header_comment_dict: Dict[str, str] = {\n        const.TRESTLE_LEVERAGING_COMP_TAG: const.YAML_LEVERAGING_COMP_COMMENT,\n        const.TRESTLE_STATEMENT_TAG: const.YAML_LEVERAGED_COMMENT\n    }\n    self.merged_header_dict: Dict[str, Any] = {\n        const.TRESTLE_STATEMENT_TAG: '',\n        const.TRESTLE_LEVERAGING_COMP_TAG: component_mapping_default,\n        const.TRESTLE_GLOBAL_TAG: {\n            const.LEVERAGED_SSP: {\n                const.HREF: leveraged_ssp_reference\n            }\n        }\n    }\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.LeveragedStatements.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                                                            Write inheritance information to a single markdown file.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            @abstractmethod\ndef write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write inheritance information to a single markdown file.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided","title":" StatementProvided (LeveragedStatements) ","text":"

                                                                            Concrete class for managing provided statements.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            class StatementProvided(LeveragedStatements):\n\"\"\"Concrete class for managing provided statements.\"\"\"\n\n    def __init__(\n        self,\n        provided_uuid: str,\n        provided_description: str,\n        leveraged_ssp_reference: str,\n    ) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self.provided_uuid = provided_uuid\n        self.provided_description = provided_description\n        super().__init__(leveraged_ssp_reference)\n\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write provided statements to a markdown file.\"\"\"\n        self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n        if self._md_file.exists():\n            return self.update_statement_md(leveraged_statement_file)\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided statements in a markdown file.\"\"\"\n        md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n        self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def _add_generated_content(self) -> None:\n        self.merged_header_dict[const.TRESTLE_STATEMENT_TAG] = {const.PROVIDED_UUID: self.provided_uuid}\n        self._md_file.add_yaml_header(self.merged_header_dict)\n\n        self._md_file.new_header(level=1, title=const.PROVIDED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.provided_description)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided.__init__","title":"__init__(self, provided_uuid, provided_description, leveraged_ssp_reference) special","text":"Source code in trestle/core/crm/leveraged_statements.py
                                                                            def __init__(\n    self,\n    provided_uuid: str,\n    provided_description: str,\n    leveraged_ssp_reference: str,\n) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self.provided_uuid = provided_uuid\n    self.provided_description = provided_description\n    super().__init__(leveraged_ssp_reference)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided.update_statement_md","title":"update_statement_md(self, leveraged_statement_file)","text":"

                                                                            Update provided statements in a markdown file.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided statements in a markdown file.\"\"\"\n    md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n    self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementProvided.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                                                            Write provided statements to a markdown file.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write provided statements to a markdown file.\"\"\"\n    self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n    if self._md_file.exists():\n        return self.update_statement_md(leveraged_statement_file)\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility","title":" StatementResponsibility (LeveragedStatements) ","text":"

                                                                            Concrete class for managing responsibility statements.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            class StatementResponsibility(LeveragedStatements):\n\"\"\"Concrete class for managing responsibility statements.\"\"\"\n\n    def __init__(\n        self,\n        responsibility_uuid: str,\n        responsibility_description: str,\n        leveraged_ssp_reference: str,\n    ) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self.responsibility_uuid = responsibility_uuid\n        self.responsibility_description = responsibility_description\n        self.satisfied_description = ''\n        super().__init__(leveraged_ssp_reference)\n\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write responsibility statements to a markdown file.\"\"\"\n        self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n        if self._md_file.exists():\n            return self.update_statement_md(leveraged_statement_file)\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update responsibility statements in a markdown file.\"\"\"\n        md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n        self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n        satisfied_description = md_reader.get_satisfied_description()\n        if satisfied_description is not None:\n            self.satisfied_description = satisfied_description\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def _add_generated_content(self) -> None:\n        self.merged_header_dict[const.TRESTLE_STATEMENT_TAG] = {const.RESPONSIBILITY_UUID: self.responsibility_uuid}\n        self._md_file.add_yaml_header(self.merged_header_dict)\n\n        self._md_file.new_header(level=1, title=const.RESPONSIBILITY_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.responsibility_description)\n        self._md_file.new_header(level=1, title=const.SATISFIED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(const.SATISFIED_STATEMENT_COMMENT)\n        self._md_file.new_line(self.satisfied_description)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility.__init__","title":"__init__(self, responsibility_uuid, responsibility_description, leveraged_ssp_reference) special","text":"Source code in trestle/core/crm/leveraged_statements.py
                                                                            def __init__(\n    self,\n    responsibility_uuid: str,\n    responsibility_description: str,\n    leveraged_ssp_reference: str,\n) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self.responsibility_uuid = responsibility_uuid\n    self.responsibility_description = responsibility_description\n    self.satisfied_description = ''\n    super().__init__(leveraged_ssp_reference)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility.update_statement_md","title":"update_statement_md(self, leveraged_statement_file)","text":"

                                                                            Update responsibility statements in a markdown file.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update responsibility statements in a markdown file.\"\"\"\n    md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n    self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n    satisfied_description = md_reader.get_satisfied_description()\n    if satisfied_description is not None:\n        self.satisfied_description = satisfied_description\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementResponsibility.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                                                            Write responsibility statements to a markdown file.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write responsibility statements to a markdown file.\"\"\"\n    self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n    if self._md_file.exists():\n        return self.update_statement_md(leveraged_statement_file)\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree","title":" StatementTree (LeveragedStatements) ","text":"

                                                                            Concrete class for managing provided and responsibility statements.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            class StatementTree(LeveragedStatements):\n\"\"\"Concrete class for managing provided and responsibility statements.\"\"\"\n\n    def __init__(\n        self,\n        provided_uuid: str,\n        provided_description: str,\n        responsibility_uuid: str,\n        responsibility_description: str,\n        leveraged_ssp_reference: str\n    ) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self.provided_uuid = provided_uuid\n        self.provided_description = provided_description\n        self.responsibility_uuid = responsibility_uuid\n        self.responsibility_description = responsibility_description\n        self.satisfied_description = ''\n        super().__init__(leveraged_ssp_reference)\n\n    def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write a provided and responsibility statements to a markdown file.\"\"\"\n        self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n        if self._md_file.exists():\n            return self.update_statement_md(leveraged_statement_file)\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided and responsibility statements in a markdown file.\"\"\"\n        md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n        self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n        satisfied_description = md_reader.get_satisfied_description()\n        if satisfied_description is not None:\n            self.satisfied_description = satisfied_description\n\n        self._add_generated_content()\n        self._md_file.write_out()\n\n    def _add_generated_content(self) -> None:\n        statement_dict: Dict[str, str] = {\n            const.PROVIDED_UUID: self.provided_uuid, const.RESPONSIBILITY_UUID: self.responsibility_uuid\n        }\n\n        self.merged_header_dict[const.TRESTLE_STATEMENT_TAG] = statement_dict\n        self._md_file.add_yaml_header(self.merged_header_dict)\n\n        self._md_file.new_header(level=1, title=const.PROVIDED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.provided_description)\n        self._md_file.new_header(level=1, title=const.RESPONSIBILITY_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(self.responsibility_description)\n        self._md_file.new_header(level=1, title=const.SATISFIED_STATEMENT_DESCRIPTION)\n        self._md_file.new_line(const.SATISFIED_STATEMENT_COMMENT)\n        self._md_file.new_line(self.satisfied_description)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree.__init__","title":"__init__(self, provided_uuid, provided_description, responsibility_uuid, responsibility_description, leveraged_ssp_reference) special","text":"Source code in trestle/core/crm/leveraged_statements.py
                                                                            def __init__(\n    self,\n    provided_uuid: str,\n    provided_description: str,\n    responsibility_uuid: str,\n    responsibility_description: str,\n    leveraged_ssp_reference: str\n) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self.provided_uuid = provided_uuid\n    self.provided_description = provided_description\n    self.responsibility_uuid = responsibility_uuid\n    self.responsibility_description = responsibility_description\n    self.satisfied_description = ''\n    super().__init__(leveraged_ssp_reference)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree.update_statement_md","title":"update_statement_md(self, leveraged_statement_file)","text":"

                                                                            Update provided and responsibility statements in a markdown file.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def update_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Update provided and responsibility statements in a markdown file.\"\"\"\n    md_reader = InheritanceMarkdownReader(leveraged_statement_file)\n\n    self.merged_header_dict[const.TRESTLE_LEVERAGING_COMP_TAG] = md_reader.get_leveraged_component_header_value()\n\n    satisfied_description = md_reader.get_satisfied_description()\n    if satisfied_description is not None:\n        self.satisfied_description = satisfied_description\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.leveraged_statements/#trestle.core.crm.leveraged_statements.StatementTree.write_statement_md","title":"write_statement_md(self, leveraged_statement_file)","text":"

                                                                            Write a provided and responsibility statements to a markdown file.

                                                                            Source code in trestle/core/crm/leveraged_statements.py
                                                                            def write_statement_md(self, leveraged_statement_file: pathlib.Path) -> None:\n\"\"\"Write a provided and responsibility statements to a markdown file.\"\"\"\n    self._md_file = MDWriter(leveraged_statement_file, self.header_comment_dict)\n\n    if self._md_file.exists():\n        return self.update_statement_md(leveraged_statement_file)\n\n    self._add_generated_content()\n    self._md_file.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/","title":"ssp_inheritance_api","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api","title":"trestle.core.crm.ssp_inheritance_api","text":"

                                                                            API for updating inheritance information in SSPs.

                                                                            "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI","title":" SSPInheritanceAPI ","text":"

                                                                            API for updating inheritance information in SSPs through inheritance markdown.

                                                                            Source code in trestle/core/crm/ssp_inheritance_api.py
                                                                            class SSPInheritanceAPI():\n\"\"\"API for updating inheritance information in SSPs through inheritance markdown.\"\"\"\n\n    def __init__(self, inheritance_md_path: pathlib.Path, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the SSP Inheritance API class.\"\"\"\n        self._inheritance_markdown_path: pathlib.Path = inheritance_md_path\n        self._trestle_root: pathlib.Path = trestle_root\n\n    def write_inheritance_as_markdown(\n        self, leveraged_ssp_reference: str, catalog_api: Optional[CatalogAPI] = None\n    ) -> None:\n\"\"\"\n        Write inheritance information to markdown.\n\n        Args:\n            leveraged_ssp_reference: Location of the SSP to write inheritance information from.\n            catalog_api: Catalog API to filter inheritance information by catalog.\n\n        Notes:\n            If a catalog API is provided, the written controls in the markdown will be filtered by the catalog.\n        \"\"\"\n        leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n        if catalog_api is not None:\n            control_imp: ossp.ControlImplementation = leveraged_ssp.control_implementation\n\n            new_imp_requirements: List[ossp.ImplementedRequirement] = []\n            for imp_requirement in as_list(control_imp.implemented_requirements):\n                control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n                if control is not None:\n                    new_imp_requirements.append(imp_requirement)\n            control_imp.implemented_requirements = new_imp_requirements\n\n            leveraged_ssp.control_implementation = control_imp\n\n        export_writer: ExportWriter = ExportWriter(\n            self._inheritance_markdown_path, leveraged_ssp, leveraged_ssp_reference\n        )\n        export_writer.write_exports_as_markdown()\n\n    def update_ssp_inheritance(self, ssp: ossp.SystemSecurityPlan) -> None:\n\"\"\"\n        Update inheritance information in SSP.\n\n        Args:\n            ssp: SSP to update with inheritance information.\n        \"\"\"\n        logger.debug('Reading inheritance information from markdown.')\n        reader = ExportReader(self._inheritance_markdown_path, ssp)\n        ssp = reader.read_exports_from_markdown()\n\n        leveraged_ssp_reference = reader.get_leveraged_ssp_href()\n\n        leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n        link: common.Link = common.Link(href=leveraged_ssp_reference)\n        leveraged_auths: List[ossp.LeveragedAuthorization] = []\n        leveraged_auth: ossp.LeveragedAuthorization = gens.generate_sample_model(ossp.LeveragedAuthorization)\n        leveraged_components: List[str] = reader.get_leveraged_components()\n\n        if not leveraged_components:\n            logger.warning(\n                'No leveraged components mapped to the SSP. '\n                'Please edit the inheritance markdown to include the leveraged authorization.'\n            )\n        else:\n            existing_leveraged_auth: ossp.LeveragedAuthorization = self._leveraged_auth_from_existing(\n                as_list(ssp.system_implementation.leveraged_authorizations), link\n            )\n            if existing_leveraged_auth is not None:\n                leveraged_auth = existing_leveraged_auth\n            else:\n                leveraged_auth.links = as_list(leveraged_auth.links)\n                leveraged_auth.links.append(link)\n\n            leveraged_auth.title = f'Leveraged Authorization for {leveraged_ssp.metadata.title}'\n            leveraged_auths.append(leveraged_auth)\n\n        # Overwrite the leveraged authorization in the SSP. The only leveraged authorization should be the one\n        # coming from inheritance view\n        ssp.system_implementation.leveraged_authorizations = none_if_empty(leveraged_auths)\n\n        self._reconcile_components(ssp, leveraged_ssp, leveraged_components, leveraged_auth)\n\n    def _fetch_leveraged_ssp(self, leveraged_ssp_reference: str) -> ossp.SystemSecurityPlan:\n\"\"\"Fetch the leveraged SSP.\"\"\"\n        leveraged_ssp: ossp.SystemSecurityPlan\n        fetcher = FetcherFactory.get_fetcher(self._trestle_root, leveraged_ssp_reference)\n        try:\n            leveraged_ssp, _ = fetcher.get_oscal()\n        except TrestleError as e:\n            raise TrestleError(f'Unable to fetch ssp from {leveraged_ssp_reference}: {e}')\n        return leveraged_ssp\n\n    def _reconcile_components(\n        self,\n        ssp: ossp.SystemSecurityPlan,\n        leveraged_ssp: ossp.SystemSecurityPlan,\n        leveraged_components: List[str],\n        leveraged_auth: ossp.LeveragedAuthorization\n    ) -> None:\n\"\"\"Reconcile components in the leveraging SSP with those in the leveraged SSP.\"\"\"\n        mapped_components: Dict[str, ossp.SystemComponent] = {}\n        for component in as_list(leveraged_ssp.system_implementation.components):\n            if component.title in leveraged_components:\n                mapped_components[component.uuid] = component\n\n        new_components: List[ossp.SystemComponent] = []\n        for component in as_list(ssp.system_implementation.components):\n            props_dict: Dict[str, str] = {prop.name: prop.value for prop in as_list(component.props)}\n\n            # If this component is part of the original SSP components, add\n            # and continue\n            if const.LEV_AUTH_UUID not in props_dict:\n                new_components.append(component)\n                continue\n\n            # If the leveraged component already exists, update the title, description, type, and status\n            original_comp_uuid = props_dict[const.INHERITED_UUID]\n            if original_comp_uuid in mapped_components:\n                original_component = mapped_components.pop(original_comp_uuid)\n                self._update_leveraged_system_component(component, original_component, leveraged_auth.uuid)\n                new_components.append(component)\n\n        # Add any remaining components to the new components\n        for component in mapped_components.values():\n            new_component: ossp.SystemComponent = gens.generate_sample_model(ossp.SystemComponent)\n            self._update_leveraged_system_component(new_component, component, leveraged_auth.uuid)\n            logger.debug(f'Adding component {new_component.title} to components.')\n            new_components.append(new_component)\n\n        ssp.system_implementation.components = new_components\n\n    @staticmethod\n    def _update_leveraged_system_component(\n        new_comp: ossp.SystemComponent, original_comp: ossp.SystemComponent, leveraged_auth_id: str\n    ) -> None:\n\"\"\"Create a leveraged system component in the context of a leveraging system component.\"\"\"\n        new_comp.type = original_comp.type\n        new_comp.title = original_comp.title\n        new_comp.description = original_comp.description\n        new_comp.status = original_comp.status\n\n        new_comp.props = [\n            common.Property(name=const.IMPLEMENTATION_POINT, value=const.IMPLEMENTATION_POINT_EXTERNAL),\n            common.Property(name=const.LEV_AUTH_UUID, value=leveraged_auth_id),\n            common.Property(name=const.INHERITED_UUID, value=original_comp.uuid)\n        ]\n\n    def _leveraged_auth_from_existing(\n        self, leveraged_authorizations: List[ossp.LeveragedAuthorization], criteria_link: common.Link\n    ) -> Optional[ossp.LeveragedAuthorization]:\n\"\"\"Return the leveraged authorization if it is present in the ssp.\"\"\"\n        for leveraged_auth in leveraged_authorizations:\n            if leveraged_auth.links and any(link.href == criteria_link.href for link in leveraged_auth.links):\n                return leveraged_auth\n        return None\n
                                                                            "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI.__init__","title":"__init__(self, inheritance_md_path, trestle_root) special","text":"

                                                                            Initialize the SSP Inheritance API class.

                                                                            Source code in trestle/core/crm/ssp_inheritance_api.py
                                                                            def __init__(self, inheritance_md_path: pathlib.Path, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the SSP Inheritance API class.\"\"\"\n    self._inheritance_markdown_path: pathlib.Path = inheritance_md_path\n    self._trestle_root: pathlib.Path = trestle_root\n
                                                                            "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI.update_ssp_inheritance","title":"update_ssp_inheritance(self, ssp)","text":"

                                                                            Update inheritance information in SSP.

                                                                            Parameters:

                                                                            Name Type Description Default ssp SystemSecurityPlan

                                                                            SSP to update with inheritance information.

                                                                            required Source code in trestle/core/crm/ssp_inheritance_api.py
                                                                            def update_ssp_inheritance(self, ssp: ossp.SystemSecurityPlan) -> None:\n\"\"\"\n    Update inheritance information in SSP.\n\n    Args:\n        ssp: SSP to update with inheritance information.\n    \"\"\"\n    logger.debug('Reading inheritance information from markdown.')\n    reader = ExportReader(self._inheritance_markdown_path, ssp)\n    ssp = reader.read_exports_from_markdown()\n\n    leveraged_ssp_reference = reader.get_leveraged_ssp_href()\n\n    leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n    link: common.Link = common.Link(href=leveraged_ssp_reference)\n    leveraged_auths: List[ossp.LeveragedAuthorization] = []\n    leveraged_auth: ossp.LeveragedAuthorization = gens.generate_sample_model(ossp.LeveragedAuthorization)\n    leveraged_components: List[str] = reader.get_leveraged_components()\n\n    if not leveraged_components:\n        logger.warning(\n            'No leveraged components mapped to the SSP. '\n            'Please edit the inheritance markdown to include the leveraged authorization.'\n        )\n    else:\n        existing_leveraged_auth: ossp.LeveragedAuthorization = self._leveraged_auth_from_existing(\n            as_list(ssp.system_implementation.leveraged_authorizations), link\n        )\n        if existing_leveraged_auth is not None:\n            leveraged_auth = existing_leveraged_auth\n        else:\n            leveraged_auth.links = as_list(leveraged_auth.links)\n            leveraged_auth.links.append(link)\n\n        leveraged_auth.title = f'Leveraged Authorization for {leveraged_ssp.metadata.title}'\n        leveraged_auths.append(leveraged_auth)\n\n    # Overwrite the leveraged authorization in the SSP. The only leveraged authorization should be the one\n    # coming from inheritance view\n    ssp.system_implementation.leveraged_authorizations = none_if_empty(leveraged_auths)\n\n    self._reconcile_components(ssp, leveraged_ssp, leveraged_components, leveraged_auth)\n
                                                                            "},{"location":"api_reference/trestle.core.crm.ssp_inheritance_api/#trestle.core.crm.ssp_inheritance_api.SSPInheritanceAPI.write_inheritance_as_markdown","title":"write_inheritance_as_markdown(self, leveraged_ssp_reference, catalog_api=None)","text":"

                                                                            Write inheritance information to markdown.

                                                                            Parameters:

                                                                            Name Type Description Default leveraged_ssp_reference str

                                                                            Location of the SSP to write inheritance information from.

                                                                            required catalog_api Optional[trestle.core.catalog.catalog_api.CatalogAPI]

                                                                            Catalog API to filter inheritance information by catalog.

                                                                            None

                                                                            Notes

                                                                            If a catalog API is provided, the written controls in the markdown will be filtered by the catalog.

                                                                            Source code in trestle/core/crm/ssp_inheritance_api.py
                                                                            def write_inheritance_as_markdown(\n    self, leveraged_ssp_reference: str, catalog_api: Optional[CatalogAPI] = None\n) -> None:\n\"\"\"\n    Write inheritance information to markdown.\n\n    Args:\n        leveraged_ssp_reference: Location of the SSP to write inheritance information from.\n        catalog_api: Catalog API to filter inheritance information by catalog.\n\n    Notes:\n        If a catalog API is provided, the written controls in the markdown will be filtered by the catalog.\n    \"\"\"\n    leveraged_ssp: ossp.SystemSecurityPlan = self._fetch_leveraged_ssp(leveraged_ssp_reference)\n\n    if catalog_api is not None:\n        control_imp: ossp.ControlImplementation = leveraged_ssp.control_implementation\n\n        new_imp_requirements: List[ossp.ImplementedRequirement] = []\n        for imp_requirement in as_list(control_imp.implemented_requirements):\n            control = catalog_api._catalog_interface.get_control(imp_requirement.control_id)\n            if control is not None:\n                new_imp_requirements.append(imp_requirement)\n        control_imp.implemented_requirements = new_imp_requirements\n\n        leveraged_ssp.control_implementation = control_imp\n\n    export_writer: ExportWriter = ExportWriter(\n        self._inheritance_markdown_path, leveraged_ssp, leveraged_ssp_reference\n    )\n    export_writer.write_exports_as_markdown()\n
                                                                            "},{"location":"api_reference/trestle.core.docs_control_writer/","title":"docs_control_writer","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer","title":"trestle.core.docs_control_writer","text":"

                                                                            Handle writing of controls to markdown for docs purposes.

                                                                            "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter","title":" DocsControlWriter (ControlWriter) ","text":"

                                                                            Class to write controls as markdown for docs purposes.

                                                                            Source code in trestle/core/docs_control_writer.py
                                                                            class DocsControlWriter(ControlWriter):\n\"\"\"Class to write controls as markdown for docs purposes.\"\"\"\n\n    def write_control_with_sections(\n        self,\n        control: cat.Control,\n        profile: prof.Profile,\n        group_title: str,\n        sections: List[str],\n        sections_dict: Optional[Dict[str, str]] = None,\n        label_column: bool = True,\n        add_group_to_title: bool = False\n    ) -> str:\n\"\"\"Write the control into markdown file with specified sections.\"\"\"\n        self._md_file = MDWriter(None)\n        self._sections_dict = sections_dict if sections_dict else {}\n        tag_pattern = '{: #[.]}'  # noqa: FS003 - not f string but tag\n        if not isinstance(group_title, str):\n            raise TrestleError(f'Group title must be provided and be a string, instead received: {group_title}')\n\n        for section in sections:\n            if 'statement' == section:\n                self._add_control_statement(control, group_title, add_group_to_title, tag_pattern=tag_pattern)\n\n            elif const.OBJECTIVE_PART == section:\n                self._add_control_objective(control, tag_pattern=tag_pattern)\n\n            elif 'table_of_parameters' == section:\n                self.get_param_table(\n                    control, label_column, section_dict=sections_dict, tag_pattern=tag_pattern, md_file=self._md_file\n                )\n            else:\n                self._add_one_section(control, profile, section, tag_pattern=tag_pattern)\n\n        return '\\n'.join(self._md_file._lines)\n\n    def get_control_statement_ssp(self, control: cat.Control) -> List[str]:\n\"\"\"Get the control statement as formatted markdown from a control formatted for SSP.\"\"\"\n        self._md_file = MDWriter(None)\n        self._add_control_statement_ssp(control)\n        return self._md_file.get_lines()\n\n    def get_param_table(\n        self,\n        control: cat.Control,\n        label_column: bool = False,\n        section_dict: Optional[Dict[str, str]] = None,\n        tag_pattern: str = None,\n        md_file: MDWriter = None\n    ) -> List[str]:\n\"\"\"Get parameters of a control as a markdown table for ssp_io, with optional third label column.\"\"\"\n\n        def _get_displayname_if_exists(param_id: str) -> str:\n            for param in as_filtered_list(control.params, lambda p: p.id == param_id):\n                for prop in as_filtered_list(param.props, lambda p: p.name == const.DISPLAY_NAME):\n                    return prop.value\n            return param_id\n\n        param_dict = ControlInterface.get_control_param_dict(control, False)\n\n        if param_dict:\n            if md_file:\n                self._md_file = md_file\n            else:\n                self._md_file = MDWriter(None)\n            header_title = 'Table of Parameters'\n            if section_dict:\n                header_title = section_dict.get(const.TABLE_OF_PARAMS_PART, 'Table of Parameters')\n            self._md_file.new_paragraph()\n            self._md_file.new_header(level=2, title=header_title, add_new_line_after_header=not tag_pattern)\n            if tag_pattern:\n                self._md_file.new_line(tag_pattern.replace('[.]', header_title.replace(' ', '-').lower()))\n                self._md_file.new_paragraph()\n            self._md_file.set_indent_level(-1)\n            if label_column:\n                self._md_file.new_table(\n                    [\n                        [\n                            _get_displayname_if_exists(key),\n                            ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_EMPTY_STRING),\n                            ControlInterface.param_to_str(param_dict[key], ParameterRep.LABEL_OR_CHOICES, True),\n                        ] for key in param_dict.keys()\n                    ], ['Parameter ID', 'Values', 'Label or Choices']\n                )\n            else:\n                self._md_file.new_table(\n                    [\n                        [\n                            _get_displayname_if_exists(key),\n                            ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_LABEL_OR_CHOICES)\n                        ] for key in param_dict.keys()\n                    ], ['Parameter ID', 'Values']\n                )\n            self._md_file.set_indent_level(-1)\n            if tag_pattern:\n                bottom_tag_pattern = '{: #\\\"Parameters for [.]\\\" caption-side=\\\"top\\\"}'  # noqa: FS003 - not f string\n                control_id = self._get_pretty_control_id_if_exists(control)\n                self._md_file.new_line(bottom_tag_pattern.replace('[.]', control_id))\n                self._md_file.new_paragraph()\n            return self._md_file.get_lines()\n\n        return []\n\n    def _add_control_statement(\n        self, control: cat.Control, group_title: str, print_group_title: bool = True, tag_pattern: str = None\n    ) -> None:\n\"\"\"Add the control statement and items to the md file.\"\"\"\n        self._md_file.new_paragraph()\n\n        group_name = ''\n        control_title = control.title\n\n        if print_group_title:\n            group_name = ' \\[' + group_title + '\\]'\n\n        control_id = self._get_pretty_control_id_if_exists(control)\n\n        title = f'{control_id} -{group_name} {control_title}'\n\n        header_title = self._sections_dict.get(const.STATEMENT, 'Control Statement')\n        self._md_file.new_header(level=1, title=title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', control.id))\n            self._md_file.new_paragraph()\n\n        self._md_file.new_header(level=2, title=header_title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', header_title.replace(' ', '-').lower()))\n            self._md_file.new_paragraph()\n\n        self._md_file.set_indent_level(-1)\n        self._add_part_and_its_items(control, const.STATEMENT, const.ITEM)\n        self._md_file.set_indent_level(-1)\n\n    def _add_control_objective(self, control: cat.Control, tag_pattern: str = None) -> None:\n        if control.parts:\n            for part in control.parts:\n                if part.name == const.OBJECTIVE_PART:\n                    self._md_file.new_paragraph()\n                    heading_title = self._sections_dict.get(const.OBJECTIVE_PART, 'Control Objective')\n                    self._md_file.new_header(level=2, title=heading_title, add_new_line_after_header=not tag_pattern)\n                    if tag_pattern:\n                        self._md_file.new_line(tag_pattern.replace('[.]', heading_title.replace(' ', '-').lower()))\n                        self._md_file.new_paragraph()\n                    self._md_file.set_indent_level(-1)\n                    self._add_part_and_its_items(control, const.OBJECTIVE_PART, const.OBJECTIVE_PART)\n                    self._md_file.set_indent_level(-1)\n                    return\n\n    def _add_one_section(\n        self, control: cat.Control, profile: prof.Profile, section: str, tag_pattern: Optional[str] = None\n    ) -> None:\n\"\"\"Add specific control section.\"\"\"\n        prose = ControlInterface.get_control_section_prose(control, section)\n        if prose:\n            section_title = self._sections_dict.get(section, section)\n            heading_title = f'{section_title}'\n            self._md_file.new_header(level=2, title=heading_title, add_new_line_after_header=not tag_pattern)\n            if tag_pattern:\n                self._md_file.new_line(tag_pattern.replace('[.]', heading_title.replace(' ', '-').lower()))\n                self._md_file.new_paragraph()\n            self._md_file.new_line(prose)\n            self._md_file.new_paragraph()\n        else:\n            # write parts and subparts if exist\n            part_infos = ControlInterface.get_all_add_info(control.id, profile)\n            for part_info in part_infos:\n                if part_info.name == section:\n                    self._write_part_info(part_info, section, tag_pattern)\n                    break\n\n    def _write_part_info(\n        self,\n        part_info: PartInfo,\n        section_name: str,\n        tag_pattern: Optional[str] = None,\n        section_prefix: str = '',\n        heading_level: int = 2\n    ) -> None:\n        section_title = self._sections_dict.get(section_name, part_info.name)\n\n        heading_title = f'{section_title}'\n        tag_section_name = section_prefix + f'{section_title}'\n        tag_section_name = re.sub(const.MATCH_ALL_EXCEPT_LETTERS_UNDERSCORE_SPACE_REGEX, '', tag_section_name)\n        tag_section_name = tag_section_name.replace(' ', '-').replace('_', '-').lower()\n        self._md_file.new_header(level=heading_level, title=heading_title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', tag_section_name))\n            self._md_file.new_paragraph()\n        prose = '' if part_info.prose is None else part_info.prose\n        self._md_file.new_line(prose)\n        self._md_file.new_paragraph()\n\n        for subpart_info in as_list(part_info.parts):\n            self._write_part_info(\n                subpart_info, subpart_info.name, tag_pattern, tag_section_name + '-', heading_level + 1\n            )\n\n    def _get_pretty_control_id_if_exists(self, control: cat.Control) -> str:\n        control_id = control.id.upper()\n        if control.props:\n            # Take control id from the properties\n            for prop in control.props:\n                if prop.name == 'label':\n                    control_id = prop.value\n                    break\n        return control_id\n\n    def _add_control_statement_ssp(self, control: cat.Control) -> None:\n\"\"\"Add the control statement and items to the markdown SSP.\"\"\"\n        self._md_file.new_paragraph()\n        label = ControlInterface.get_label(control)\n        label = label if label else control.id.upper()\n        title = f'{label} - {control.title}'\n        self._md_file.new_header(level=1, title=title)\n        self._md_file.new_header(level=2, title='Control Statement')\n        self._md_file.set_indent_level(-1)\n        self._add_part_and_its_items(control, const.STATEMENT, const.ITEM)\n        self._md_file.set_indent_level(-1)\n
                                                                            "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter.get_control_statement_ssp","title":"get_control_statement_ssp(self, control)","text":"

                                                                            Get the control statement as formatted markdown from a control formatted for SSP.

                                                                            Source code in trestle/core/docs_control_writer.py
                                                                            def get_control_statement_ssp(self, control: cat.Control) -> List[str]:\n\"\"\"Get the control statement as formatted markdown from a control formatted for SSP.\"\"\"\n    self._md_file = MDWriter(None)\n    self._add_control_statement_ssp(control)\n    return self._md_file.get_lines()\n
                                                                            "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter.get_param_table","title":"get_param_table(self, control, label_column=False, section_dict=None, tag_pattern=None, md_file=None)","text":"

                                                                            Get parameters of a control as a markdown table for ssp_io, with optional third label column.

                                                                            Source code in trestle/core/docs_control_writer.py
                                                                            def get_param_table(\n    self,\n    control: cat.Control,\n    label_column: bool = False,\n    section_dict: Optional[Dict[str, str]] = None,\n    tag_pattern: str = None,\n    md_file: MDWriter = None\n) -> List[str]:\n\"\"\"Get parameters of a control as a markdown table for ssp_io, with optional third label column.\"\"\"\n\n    def _get_displayname_if_exists(param_id: str) -> str:\n        for param in as_filtered_list(control.params, lambda p: p.id == param_id):\n            for prop in as_filtered_list(param.props, lambda p: p.name == const.DISPLAY_NAME):\n                return prop.value\n        return param_id\n\n    param_dict = ControlInterface.get_control_param_dict(control, False)\n\n    if param_dict:\n        if md_file:\n            self._md_file = md_file\n        else:\n            self._md_file = MDWriter(None)\n        header_title = 'Table of Parameters'\n        if section_dict:\n            header_title = section_dict.get(const.TABLE_OF_PARAMS_PART, 'Table of Parameters')\n        self._md_file.new_paragraph()\n        self._md_file.new_header(level=2, title=header_title, add_new_line_after_header=not tag_pattern)\n        if tag_pattern:\n            self._md_file.new_line(tag_pattern.replace('[.]', header_title.replace(' ', '-').lower()))\n            self._md_file.new_paragraph()\n        self._md_file.set_indent_level(-1)\n        if label_column:\n            self._md_file.new_table(\n                [\n                    [\n                        _get_displayname_if_exists(key),\n                        ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_EMPTY_STRING),\n                        ControlInterface.param_to_str(param_dict[key], ParameterRep.LABEL_OR_CHOICES, True),\n                    ] for key in param_dict.keys()\n                ], ['Parameter ID', 'Values', 'Label or Choices']\n            )\n        else:\n            self._md_file.new_table(\n                [\n                    [\n                        _get_displayname_if_exists(key),\n                        ControlInterface.param_to_str(param_dict[key], ParameterRep.VALUE_OR_LABEL_OR_CHOICES)\n                    ] for key in param_dict.keys()\n                ], ['Parameter ID', 'Values']\n            )\n        self._md_file.set_indent_level(-1)\n        if tag_pattern:\n            bottom_tag_pattern = '{: #\\\"Parameters for [.]\\\" caption-side=\\\"top\\\"}'  # noqa: FS003 - not f string\n            control_id = self._get_pretty_control_id_if_exists(control)\n            self._md_file.new_line(bottom_tag_pattern.replace('[.]', control_id))\n            self._md_file.new_paragraph()\n        return self._md_file.get_lines()\n\n    return []\n
                                                                            "},{"location":"api_reference/trestle.core.docs_control_writer/#trestle.core.docs_control_writer.DocsControlWriter.write_control_with_sections","title":"write_control_with_sections(self, control, profile, group_title, sections, sections_dict=None, label_column=True, add_group_to_title=False)","text":"

                                                                            Write the control into markdown file with specified sections.

                                                                            Source code in trestle/core/docs_control_writer.py
                                                                            def write_control_with_sections(\n    self,\n    control: cat.Control,\n    profile: prof.Profile,\n    group_title: str,\n    sections: List[str],\n    sections_dict: Optional[Dict[str, str]] = None,\n    label_column: bool = True,\n    add_group_to_title: bool = False\n) -> str:\n\"\"\"Write the control into markdown file with specified sections.\"\"\"\n    self._md_file = MDWriter(None)\n    self._sections_dict = sections_dict if sections_dict else {}\n    tag_pattern = '{: #[.]}'  # noqa: FS003 - not f string but tag\n    if not isinstance(group_title, str):\n        raise TrestleError(f'Group title must be provided and be a string, instead received: {group_title}')\n\n    for section in sections:\n        if 'statement' == section:\n            self._add_control_statement(control, group_title, add_group_to_title, tag_pattern=tag_pattern)\n\n        elif const.OBJECTIVE_PART == section:\n            self._add_control_objective(control, tag_pattern=tag_pattern)\n\n        elif 'table_of_parameters' == section:\n            self.get_param_table(\n                control, label_column, section_dict=sections_dict, tag_pattern=tag_pattern, md_file=self._md_file\n            )\n        else:\n            self._add_one_section(control, profile, section, tag_pattern=tag_pattern)\n\n    return '\\n'.join(self._md_file._lines)\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/","title":"draw_io","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io","title":"trestle.core.draw_io","text":"

                                                                            Functionality for reading information from a drawio file.

                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO","title":" DrawIO ","text":"

                                                                            Access and process drawio data / metadata.

                                                                            Source code in trestle/core/draw_io.py
                                                                            class DrawIO():\n\"\"\"Access and process drawio data / metadata.\"\"\"\n\n    def __init__(self, file_path: pathlib.Path) -> None:\n\"\"\"\n        Load drawio object into memory.\n\n        args:\n            file_path: Path to the drawio object.\n        \"\"\"\n        self.file_path: pathlib.Path = file_path\n        self._load()\n        self.banned_keys = ['id', 'label']\n\n    def _load(self) -> None:\n\"\"\"Load the file.\"\"\"\n        if not self.file_path.exists() or self.file_path.is_dir():\n            raise TrestleError(f'Candidate drawio file {str(self.file_path)} does not exist or is a directory')\n        try:\n            self.raw_xml = defusedxml.ElementTree.parse(self.file_path, forbid_dtd=True)\n        except Exception as e:\n            raise TrestleError(f'Exception loading Element tree from file: {e}')\n        self.mx_file = self.raw_xml.getroot()\n        if not self.mx_file.tag == 'mxfile':\n            raise TrestleError('DrawIO file is not a draw io file (mxfile)')\n        self.diagrams = []\n        for diagram in list(self.mx_file):\n            # Determine if compressed or not\n            # Assumption 1 mxGraphModel\n            n_children = len(list(diagram))\n            if n_children == 0:\n                # Compressed object\n                self.diagrams.append(self._uncompress(diagram.text))\n            elif n_children == 1:\n                self.diagrams.append(list(diagram)[0])\n            else:\n                raise TrestleError('Unhandled behaviour in drawio read.')\n\n    def _uncompress(self, compressed_text: str) -> Element:\n\"\"\"\n        Given a compressed object from a drawio file return an xml element for the mxGraphModel.\n\n        Args:\n            compressed_text: A compressed mxGraphModel from inside an mxfile\n\n        Returns:\n            An element containing the mxGraphModel\n        \"\"\"\n        # Assume b64 encode\n        decoded = base64.b64decode(compressed_text)\n        clean_text = unquote(zlib.decompress(decoded, -15).decode(const.FILE_ENCODING))\n        element = defusedxml.ElementTree.fromstring(clean_text, forbid_dtd=True)\n        if not element.tag == 'mxGraphModel':\n            raise TrestleError('Unknown data structure within a compressed drawio file.')\n        return element\n\n    def get_metadata(self) -> List[Dict[str, str]]:\n\"\"\"Get metadata from each tab if it exists or provide an empty dict.\"\"\"\n        # Note that id and label are special for drawio.\n        md_list: List[Dict[str, str]] = []\n        for diagram in self.diagrams:\n            md_dict: Dict[str, str] = {}\n            # Drawio creates data within a root and then an object element type\n            children = list(diagram)\n            root_obj = children[0]\n            md_objects = root_obj.findall('object')\n            # Should always be true - to test presumptions.\n            if len(md_objects) == 0:\n                md_list.append(md_dict)\n                continue\n            items = md_objects[0].items()\n            for item in items:\n                key = item[0]\n                val = item[1]\n                if key in self.banned_keys:\n                    continue\n                md_dict[key] = val\n            md_list.append(md_dict)\n        return md_list\n\n    @classmethod\n    def restructure_metadata(cls, input_dict: Dict[str, str]) -> Dict[str, Any]:\n\"\"\"Restructure metadata into a hierarchial dict assuming a period separator.\"\"\"\n        # get the list of duplicate keys\n        # Get a count of keys\n        result = {}\n        key_map = {}\n        for keys in input_dict.keys():\n            stub = keys.split('.')[0]\n            tmp = key_map.get(stub, [])\n            tmp.append(keys)\n            key_map[stub] = tmp\n\n        for key, values in key_map.items():\n            holding = {}\n            if len(values) == 1 and key == values[0]:\n                result[key] = input_dict[key]\n            else:\n                for value in values:\n                    holding[value.split('.', 1)[-1]] = input_dict[value]\n                result[key] = cls.restructure_metadata(holding)\n        return result\n\n    def write_drawio_with_metadata(\n        self, path: pathlib.Path, metadata: Dict, diagram_metadata_idx: int, target_path: pathlib.Path = None\n    ) -> None:\n\"\"\"\n        Write modified metadata to drawio file.\n\n        Writes given metadata to 'object' element attributes inside of the selected drawio diagram element.\n        Currently supports writing only uncompressed elements.\n\n        Args:\n            path: path to write modified drawio file to\n            metadata: dictionary of modified metadata to insert to drawio\n            diagram_metadata_idx: index of diagram which metadata was modified\n            target_path: if not provided the changes will be written to path\n        \"\"\"\n        flattened_dict = self._flatten_dictionary(metadata)\n        if diagram_metadata_idx >= len(list(self.diagrams)):\n            raise TrestleError(f'Drawio file {path} does not contain a diagram for index {diagram_metadata_idx}')\n\n        diagram = list(self.diagrams)[diagram_metadata_idx]\n        children = list(diagram)\n        root_obj = children[0]\n        md_objects = root_obj.findall('object')\n        if len(md_objects) == 0:\n            raise TrestleError(f'Unable to write metadata, diagram in drawio file {path} does not have objects.')\n\n        for key in md_objects[0].attrib.copy():\n            if key not in flattened_dict.keys() and key not in self.banned_keys:\n                # outdated key delete\n                del md_objects[0].attrib[key]\n                continue\n            if key in self.banned_keys:\n                continue\n            md_objects[0].attrib[key] = flattened_dict[key]\n        for key in flattened_dict.keys():\n            if key in self.banned_keys:\n                continue\n            md_objects[0].attrib[key] = flattened_dict[key]\n        parent_diagram = self.mx_file.findall('diagram')[diagram_metadata_idx]\n        if len(parent_diagram.findall('mxGraphModel')) == 0:\n            parent_diagram.insert(0, diagram)\n\n        if target_path:\n            self.raw_xml.write(target_path)\n        else:\n            self.raw_xml.write(path)\n\n    def _flatten_dictionary(self, metadata: Dict, parent_key='', separator='.') -> Dict[str, str]:\n\"\"\"Flatten hierarchial dict back to xml attributes.\"\"\"\n        items = []\n        for key, value in metadata.items():\n            new_key = parent_key + separator + key if parent_key else key\n            if isinstance(value, Dict):\n                items.extend(self._flatten_dictionary(value, new_key, separator).items())\n            else:\n                items.append((new_key, value))\n        return dict(items)\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.__init__","title":"__init__(self, file_path) special","text":"

                                                                            Load drawio object into memory.

                                                                            Parameters:

                                                                            Name Type Description Default file_path Path

                                                                            Path to the drawio object.

                                                                            required Source code in trestle/core/draw_io.py
                                                                            def __init__(self, file_path: pathlib.Path) -> None:\n\"\"\"\n    Load drawio object into memory.\n\n    args:\n        file_path: Path to the drawio object.\n    \"\"\"\n    self.file_path: pathlib.Path = file_path\n    self._load()\n    self.banned_keys = ['id', 'label']\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.get_metadata","title":"get_metadata(self)","text":"

                                                                            Get metadata from each tab if it exists or provide an empty dict.

                                                                            Source code in trestle/core/draw_io.py
                                                                            def get_metadata(self) -> List[Dict[str, str]]:\n\"\"\"Get metadata from each tab if it exists or provide an empty dict.\"\"\"\n    # Note that id and label are special for drawio.\n    md_list: List[Dict[str, str]] = []\n    for diagram in self.diagrams:\n        md_dict: Dict[str, str] = {}\n        # Drawio creates data within a root and then an object element type\n        children = list(diagram)\n        root_obj = children[0]\n        md_objects = root_obj.findall('object')\n        # Should always be true - to test presumptions.\n        if len(md_objects) == 0:\n            md_list.append(md_dict)\n            continue\n        items = md_objects[0].items()\n        for item in items:\n            key = item[0]\n            val = item[1]\n            if key in self.banned_keys:\n                continue\n            md_dict[key] = val\n        md_list.append(md_dict)\n    return md_list\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.restructure_metadata","title":"restructure_metadata(input_dict) classmethod","text":"

                                                                            Restructure metadata into a hierarchial dict assuming a period separator.

                                                                            Source code in trestle/core/draw_io.py
                                                                            @classmethod\ndef restructure_metadata(cls, input_dict: Dict[str, str]) -> Dict[str, Any]:\n\"\"\"Restructure metadata into a hierarchial dict assuming a period separator.\"\"\"\n    # get the list of duplicate keys\n    # Get a count of keys\n    result = {}\n    key_map = {}\n    for keys in input_dict.keys():\n        stub = keys.split('.')[0]\n        tmp = key_map.get(stub, [])\n        tmp.append(keys)\n        key_map[stub] = tmp\n\n    for key, values in key_map.items():\n        holding = {}\n        if len(values) == 1 and key == values[0]:\n            result[key] = input_dict[key]\n        else:\n            for value in values:\n                holding[value.split('.', 1)[-1]] = input_dict[value]\n            result[key] = cls.restructure_metadata(holding)\n    return result\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIO.write_drawio_with_metadata","title":"write_drawio_with_metadata(self, path, metadata, diagram_metadata_idx, target_path=None)","text":"

                                                                            Write modified metadata to drawio file.

                                                                            Writes given metadata to 'object' element attributes inside of the selected drawio diagram element. Currently supports writing only uncompressed elements.

                                                                            Parameters:

                                                                            Name Type Description Default path Path

                                                                            path to write modified drawio file to

                                                                            required metadata Dict

                                                                            dictionary of modified metadata to insert to drawio

                                                                            required diagram_metadata_idx int

                                                                            index of diagram which metadata was modified

                                                                            required target_path Path

                                                                            if not provided the changes will be written to path

                                                                            None Source code in trestle/core/draw_io.py
                                                                            def write_drawio_with_metadata(\n    self, path: pathlib.Path, metadata: Dict, diagram_metadata_idx: int, target_path: pathlib.Path = None\n) -> None:\n\"\"\"\n    Write modified metadata to drawio file.\n\n    Writes given metadata to 'object' element attributes inside of the selected drawio diagram element.\n    Currently supports writing only uncompressed elements.\n\n    Args:\n        path: path to write modified drawio file to\n        metadata: dictionary of modified metadata to insert to drawio\n        diagram_metadata_idx: index of diagram which metadata was modified\n        target_path: if not provided the changes will be written to path\n    \"\"\"\n    flattened_dict = self._flatten_dictionary(metadata)\n    if diagram_metadata_idx >= len(list(self.diagrams)):\n        raise TrestleError(f'Drawio file {path} does not contain a diagram for index {diagram_metadata_idx}')\n\n    diagram = list(self.diagrams)[diagram_metadata_idx]\n    children = list(diagram)\n    root_obj = children[0]\n    md_objects = root_obj.findall('object')\n    if len(md_objects) == 0:\n        raise TrestleError(f'Unable to write metadata, diagram in drawio file {path} does not have objects.')\n\n    for key in md_objects[0].attrib.copy():\n        if key not in flattened_dict.keys() and key not in self.banned_keys:\n            # outdated key delete\n            del md_objects[0].attrib[key]\n            continue\n        if key in self.banned_keys:\n            continue\n        md_objects[0].attrib[key] = flattened_dict[key]\n    for key in flattened_dict.keys():\n        if key in self.banned_keys:\n            continue\n        md_objects[0].attrib[key] = flattened_dict[key]\n    parent_diagram = self.mx_file.findall('diagram')[diagram_metadata_idx]\n    if len(parent_diagram.findall('mxGraphModel')) == 0:\n        parent_diagram.insert(0, diagram)\n\n    if target_path:\n        self.raw_xml.write(target_path)\n    else:\n        self.raw_xml.write(path)\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator","title":" DrawIOMetadataValidator ","text":"

                                                                            Validator to check whether drawio metadata meets validation expectations.

                                                                            Source code in trestle/core/draw_io.py
                                                                            class DrawIOMetadataValidator():\n\"\"\"Validator to check whether drawio metadata meets validation expectations.\"\"\"\n\n    def __init__(self, template_path: pathlib.Path, must_be_first_tab: bool = True) -> None:\n\"\"\"\n        Initialize drawio validator.\n\n        Args:\n            template_path: Path to a templated drawio file where metadata will be looked up on the first tab only.\n            must_be_first_tab: Whether to search the candidate file for a metadata across multiple tabs.\n        \"\"\"\n        self.template_path = template_path\n        self.must_be_first_tab = must_be_first_tab\n        # Load metadat from template\n        template_drawio = DrawIO(self.template_path)\n        # Zero index as must be first tab\n        self.template_metadata = template_drawio.get_metadata()[0]\n        self.template_version = MarkdownValidator.extract_template_version(self.template_metadata)\n        if self.template_version not in str(self.template_path):\n            raise TrestleError(\n                f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n                + f'Move the template to the folder {self.template_version}'\n            )\n        if 'Version' in self.template_metadata.keys() and self.template_metadata['Version'] != self.template_version:\n            raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n\n    def validate(self, candidate: pathlib.Path) -> bool:\n\"\"\"\n        Run drawio validation against a candidate file.\n\n        Args:\n            candidate: The path to a candidate markdown file to be validated.\n\n        Returns:\n            Whether or not the validation passes.\n\n        Raises:\n            err.TrestleError: If a file IO / formatting error occurs.\n        \"\"\"\n        logging.info(f'Validating drawio file {candidate} against template file {self.template_path}')\n        candidate_drawio = DrawIO(candidate)\n        drawio_metadata = candidate_drawio.get_metadata()\n\n        if self.must_be_first_tab:\n            return MarkdownValidator.compare_keys(self.template_metadata, drawio_metadata[0])\n        for md_tab in drawio_metadata:\n            status = MarkdownValidator.compare_keys(self.template_metadata, md_tab)\n            if status:\n                return status\n        return False\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator.__init__","title":"__init__(self, template_path, must_be_first_tab=True) special","text":"

                                                                            Initialize drawio validator.

                                                                            Parameters:

                                                                            Name Type Description Default template_path Path

                                                                            Path to a templated drawio file where metadata will be looked up on the first tab only.

                                                                            required must_be_first_tab bool

                                                                            Whether to search the candidate file for a metadata across multiple tabs.

                                                                            True Source code in trestle/core/draw_io.py
                                                                            def __init__(self, template_path: pathlib.Path, must_be_first_tab: bool = True) -> None:\n\"\"\"\n    Initialize drawio validator.\n\n    Args:\n        template_path: Path to a templated drawio file where metadata will be looked up on the first tab only.\n        must_be_first_tab: Whether to search the candidate file for a metadata across multiple tabs.\n    \"\"\"\n    self.template_path = template_path\n    self.must_be_first_tab = must_be_first_tab\n    # Load metadat from template\n    template_drawio = DrawIO(self.template_path)\n    # Zero index as must be first tab\n    self.template_metadata = template_drawio.get_metadata()[0]\n    self.template_version = MarkdownValidator.extract_template_version(self.template_metadata)\n    if self.template_version not in str(self.template_path):\n        raise TrestleError(\n            f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n            + f'Move the template to the folder {self.template_version}'\n        )\n    if 'Version' in self.template_metadata.keys() and self.template_metadata['Version'] != self.template_version:\n        raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n
                                                                            "},{"location":"api_reference/trestle.core.draw_io/#trestle.core.draw_io.DrawIOMetadataValidator.validate","title":"validate(self, candidate)","text":"

                                                                            Run drawio validation against a candidate file.

                                                                            Parameters:

                                                                            Name Type Description Default candidate Path

                                                                            The path to a candidate markdown file to be validated.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            Whether or not the validation passes.

                                                                            Exceptions:

                                                                            Type Description err.TrestleError

                                                                            If a file IO / formatting error occurs.

                                                                            Source code in trestle/core/draw_io.py
                                                                            def validate(self, candidate: pathlib.Path) -> bool:\n\"\"\"\n    Run drawio validation against a candidate file.\n\n    Args:\n        candidate: The path to a candidate markdown file to be validated.\n\n    Returns:\n        Whether or not the validation passes.\n\n    Raises:\n        err.TrestleError: If a file IO / formatting error occurs.\n    \"\"\"\n    logging.info(f'Validating drawio file {candidate} against template file {self.template_path}')\n    candidate_drawio = DrawIO(candidate)\n    drawio_metadata = candidate_drawio.get_metadata()\n\n    if self.must_be_first_tab:\n        return MarkdownValidator.compare_keys(self.template_metadata, drawio_metadata[0])\n    for md_tab in drawio_metadata:\n        status = MarkdownValidator.compare_keys(self.template_metadata, md_tab)\n        if status:\n            return status\n    return False\n
                                                                            "},{"location":"api_reference/trestle.core.duplicates_validator/","title":"duplicates_validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator","title":"trestle.core.duplicates_validator","text":"

                                                                            Validate by confirming no duplicate uuids.

                                                                            "},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator.DuplicatesValidator","title":" DuplicatesValidator (Validator) ","text":"

                                                                            Validator to check for duplicate uuids and param_ids in the model.

                                                                            Source code in trestle/core/duplicates_validator.py
                                                                            class DuplicatesValidator(Validator):\n\"\"\"Validator to check for duplicate uuids and param_ids in the model.\"\"\"\n\n    def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n        Test if the model is valid and contains no duplicate uuids or param_ids.\n\n        args:\n            model: An Oscal model that can be passed to the validator.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if the model does not contain duplicate uuid's.\n        \"\"\"\n        if not ModelUtils.has_no_duplicate_values_by_name(model, 'uuid'):\n            return False\n        # only profile, comp-def and ssp have set-params and only set-params have param_id\n        # param_id is required to be unique in profiles but not in other models\n        if isinstance(model, Profile):\n            return ModelUtils.has_no_duplicate_values_by_name(model, 'param_id')\n        return True\n
                                                                            "},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator.DuplicatesValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.duplicates_validator/#trestle.core.duplicates_validator.DuplicatesValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                                                            Test if the model is valid and contains no duplicate uuids or param_ids.

                                                                            Parameters:

                                                                            Name Type Description Default model OscalBaseModel

                                                                            An Oscal model that can be passed to the validator.

                                                                            required quiet bool

                                                                            Don't report msgs unless invalid.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            True (valid) if the model does not contain duplicate uuid's.

                                                                            Source code in trestle/core/duplicates_validator.py
                                                                            def model_is_valid(self, model: OscalBaseModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None) -> bool:\n\"\"\"\n    Test if the model is valid and contains no duplicate uuids or param_ids.\n\n    args:\n        model: An Oscal model that can be passed to the validator.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if the model does not contain duplicate uuid's.\n    \"\"\"\n    if not ModelUtils.has_no_duplicate_values_by_name(model, 'uuid'):\n        return False\n    # only profile, comp-def and ssp have set-params and only set-params have param_id\n    # param_id is required to be unique in profiles but not in other models\n    if isinstance(model, Profile):\n        return ModelUtils.has_no_duplicate_values_by_name(model, 'param_id')\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.generators/","title":"generators","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators","title":"trestle.core.generators","text":"

                                                                            Capabilities to allow the generation of various oscal objects.

                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.TG","title":"TG","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_base64","title":"sample_base64","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_base64_value","title":"sample_base64_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_date_value","title":"sample_date_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_method","title":"sample_method","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_observation_type_valid_value","title":"sample_observation_type_valid_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.sample_task_valid_value","title":"sample_task_valid_value","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.type_base64","title":"type_base64","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.generate_sample_model","title":"generate_sample_model(model, include_optional=False, depth=-1)","text":"

                                                                            Given a model class, generate an object of that class with sample values.

                                                                            Can generate optional variables with an enabled flag. Any array objects will have a single entry injected into it.

                                                                            Note: Trestle generate will not activate recursive loops irrespective of the depth flag.

                                                                            Parameters:

                                                                            Name Type Description Default model Union[Type[~TG], List[~TG], Dict[str, ~TG]]

                                                                            The model type provided. Typically for a user as an OscalBaseModel Subclass.

                                                                            required include_optional bool

                                                                            Whether or not to generate optional fields.

                                                                            False depth int

                                                                            Depth of the tree at which optional fields are generated. Negative values (default) removes the limit.

                                                                            -1

                                                                            Returns:

                                                                            Type Description ~TG

                                                                            The generated instance with a pro-forma values filled out as best as possible.

                                                                            Source code in trestle/core/generators.py
                                                                            def generate_sample_model(\n    model: Union[Type[TG], List[TG], Dict[str, TG]], include_optional: bool = False, depth: int = -1\n) -> TG:\n\"\"\"Given a model class, generate an object of that class with sample values.\n\n    Can generate optional variables with an enabled flag. Any array objects will have a single entry injected into it.\n\n    Note: Trestle generate will not activate recursive loops irrespective of the depth flag.\n\n    Args:\n        model: The model type provided. Typically for a user as an OscalBaseModel Subclass.\n        include_optional: Whether or not to generate optional fields.\n        depth: Depth of the tree at which optional fields are generated. Negative values (default) removes the limit.\n\n    Returns:\n        The generated instance with a pro-forma values filled out as best as possible.\n    \"\"\"\n    effective_optional = include_optional and not depth == 0\n\n    model_type = model\n    # This block normalizes model type down to\n    if utils.is_collection_field_type(model):  # type: ignore\n        model_type = utils.get_origin(model)  # type: ignore\n        model = utils.get_inner_type(model)  # type: ignore\n    model = cast(TG, model)  # type: ignore\n\n    model_dict = {}  # type: ignore\n    # this block is needed to avoid situations where an inbuilt is inside a list / dict.\n    # the only time dict ever appears is with include_all, which is handled specially\n    # the only type of collection possible after OSCAL 1.0.0 is list\n    if safe_is_sub(model, OscalBaseModel):\n        for field in model.__fields__:  # type: ignore\n            if model_type in [OscalVersion]:\n                model_dict[field] = OSCAL_VERSION\n                break\n            if field == 'include_all':\n                if include_optional:\n                    model_dict[field] = {}\n                continue\n            outer_type = model.__fields__[field].outer_type_  # type: ignore\n            # next appears to be needed for python 3.7\n            if utils.get_origin(outer_type) == Union:\n                outer_type = outer_type.__args__[0]\n            if model.__fields__[field].required or effective_optional:  # type: ignore\n                # FIXME could be ForwardRef('SystemComponentStatus')\n                if utils.is_collection_field_type(outer_type):\n                    inner_type = utils.get_inner_type(outer_type)\n                    if inner_type == model:\n                        continue\n                    model_dict[field] = generate_sample_model(\n                        outer_type, include_optional=include_optional, depth=depth - 1\n                    )\n                elif is_by_type(outer_type):\n                    model_dict[field] = generate_sample_value_by_type(outer_type, field)\n                elif safe_is_sub(outer_type, OscalBaseModel):\n                    model_dict[field] = generate_sample_model(\n                        outer_type, include_optional=include_optional, depth=depth - 1\n                    )\n                else:\n                    # Handle special cases (hacking)\n                    if model_type in [Base64Datatype]:\n                        model_dict[field] = sample_base64_value\n                    elif model_type in [Base64]:\n                        if field == 'filename':\n                            model_dict[field] = sample_base64.filename\n                        elif field == 'media_type':\n                            model_dict[field] = sample_base64.media_type\n                        elif field == 'value':\n                            model_dict[field] = sample_base64.value\n                    elif model_type in [DateDatatype]:\n                        model_dict[field] = sample_date_value\n                    # Hacking here:\n                    # Root models should ideally not exist, however, sometimes we are stuck with them.\n                    # If that is the case we need sufficient information on the type in order to generate a model.\n                    # E.g. we need the type of the container.\n                    elif field == '__root__' and hasattr(model, '__name__'):\n                        model_dict[field] = generate_sample_value_by_type(\n                            outer_type, str_utils.classname_to_alias(model.__name__, AliasMode.FIELD)\n                        )\n                    else:\n                        model_dict[field] = generate_sample_value_by_type(outer_type, field)\n        # Note: this assumes list constrains in oscal are always 1 as a minimum size. if two this may still fail.\n    else:\n        if model_type is list:\n            return [generate_sample_value_by_type(model, '')]  # type: ignore\n        if model_type is dict:\n            return {const.REPLACE_ME: generate_sample_value_by_type(model, '')}  # type: ignore\n        raise err.TrestleError('Unhandled collection type.')\n    if model_type is list:\n        return [model(**model_dict)]  # type: ignore\n    if model_type is dict:\n        return {const.REPLACE_ME: model(**model_dict)}  # type: ignore\n    return model(**model_dict)  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.generate_sample_value_by_type","title":"generate_sample_value_by_type(type_, field_name)","text":"

                                                                            Given a type, return sample value.

                                                                            Includes the Optional use of passing down a parent_model

                                                                            Source code in trestle/core/generators.py
                                                                            def generate_sample_value_by_type(\n    type_: type,\n    field_name: str,\n) -> Union[datetime, bool, int, str, float, Enum]:\n\"\"\"Given a type, return sample value.\n\n    Includes the Optional use of passing down a parent_model\n    \"\"\"\n    # FIXME: Should be in separate generator module as it inherits EVERYTHING\n    if is_enum_method(type_):\n        return sample_method\n    if is_enum_task_valid_value(type_):\n        return sample_task_valid_value\n    if is_enum_observation_type_valid_value(type_):\n        return sample_observation_type_valid_value\n    if type_ is Base64:\n        return sample_base64\n    if type_ is datetime:\n        return datetime.now().astimezone()\n    if type_ is bool:\n        return False\n    if type_ is int:\n        return 0\n    if type_ is float:\n        return 0.00\n    if safe_is_sub(type_, ConstrainedStr) or (hasattr(type_, '__name__') and 'ConstrainedStr' in type_.__name__):\n        # This code here is messy. we need to meet a set of constraints. If we do\n        # TODO: handle regex directly\n        if 'uuid' == field_name:\n            return str(uuid.uuid4())\n        # some things like location_uuid in lists arrive here with field_name=''\n        if type_.regex and type_.regex.pattern.startswith('^[0-9A-Fa-f]{8}'):  # type: ignore\n            return const.SAMPLE_UUID_STR\n        if field_name == 'date_authorized':\n            return str(date.today().isoformat())\n        if field_name == 'oscal_version':\n            return OSCAL_VERSION\n        if 'uuid' in field_name:\n            return const.SAMPLE_UUID_STR\n        # Only case where are UUID is required but not in name.\n        if field_name.rstrip('s') == 'member_of_organization':\n            return const.SAMPLE_UUID_STR\n        return const.REPLACE_ME\n    if hasattr(type_, '__name__') and 'ConstrainedIntValue' in type_.__name__:\n        # create an int value as close to the floor as possible does not test upper bound\n        multiple = type_.multiple_of if type_.multiple_of else 1  # type: ignore # default to every integer\n        # this command is a bit of a problem\n        floor = type_.ge if type_.ge else 0  # type: ignore\n        floor = type_.gt + 1 if type_.gt else floor  # type: ignore\n        if math.remainder(floor, multiple) == 0:\n            return floor\n        return (floor + 1) * multiple\n    if safe_is_sub(type_, Enum):\n        # keys and values diverge due to hypens in oscal names\n        return type_(list(type_.__members__.values())[0])  # type: ignore\n    if type_ is str:\n        if field_name == 'oscal_version':\n            return OSCAL_VERSION\n        return const.REPLACE_ME\n    if type_ is pydantic.v1.networks.EmailStr:\n        return pydantic.v1.networks.EmailStr('dummy@sample.com')\n    if type_ is pydantic.v1.networks.AnyUrl:\n        # TODO: Cleanup: this should be usable from a url.. but it's not inuitive.\n        return pydantic.v1.networks.AnyUrl('https://sample.com/replaceme.html', scheme='http', host='sample.com')\n    if type_ is list:\n        raise err.TrestleError(f'Unable to generate sample for type {type_}')\n    # default to empty dict for anything else\n    return {}  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_by_type","title":"is_by_type(model_type)","text":"

                                                                            Check for by type.

                                                                            Source code in trestle/core/generators.py
                                                                            def is_by_type(model_type: Union[Type[TG], List[TG], Dict[str, TG]]) -> bool:\n\"\"\"Check for by type.\"\"\"\n    rval = False\n    if model_type == type_base64:\n        rval = True\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_enum_method","title":"is_enum_method(type_)","text":"

                                                                            Test for method.

                                                                            Source code in trestle/core/generators.py
                                                                            def is_enum_method(type_: type) -> bool:\n\"\"\"Test for method.\"\"\"\n    rval = False\n    if utils.get_origin(type_) == Union:\n        args = typing.get_args(type_)\n        for arg in args:\n            if \"<enum 'Methods'>\" == f'{arg}':\n                rval = True\n                break\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_enum_observation_type_valid_value","title":"is_enum_observation_type_valid_value(type_)","text":"

                                                                            Test for observation type valid value.

                                                                            Source code in trestle/core/generators.py
                                                                            def is_enum_observation_type_valid_value(type_: type) -> bool:\n\"\"\"Test for observation type valid value.\"\"\"\n    rval = False\n    if utils.get_origin(type_) == Union:\n        args = typing.get_args(type_)\n        for arg in args:\n            if \"<enum 'ObservationTypeValidValues'>\" == f'{arg}':\n                rval = True\n                break\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.is_enum_task_valid_value","title":"is_enum_task_valid_value(type_)","text":"

                                                                            Test for task valid value.

                                                                            Source code in trestle/core/generators.py
                                                                            def is_enum_task_valid_value(type_: type) -> bool:\n\"\"\"Test for task valid value.\"\"\"\n    rval = False\n    if utils.get_origin(type_) == Union:\n        args = typing.get_args(type_)\n        for arg in args:\n            if \"<enum 'TaskValidValues'>\" == f'{arg}':\n                rval = True\n                break\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.core.generators/#trestle.core.generators.safe_is_sub","title":"safe_is_sub(sub, parent)","text":"

                                                                            Is this a subclass of parent.

                                                                            Source code in trestle/core/generators.py
                                                                            def safe_is_sub(sub: Any, parent: Any) -> bool:\n\"\"\"Is this a subclass of parent.\"\"\"\n    is_class = inspect.isclass(sub)\n    return is_class and issubclass(sub, parent)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/","title":"generic_oscal","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal","title":"trestle.core.generic_oscal","text":"

                                                                            Generic classes to support both SSP and DefinedComponents.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.IMPLEMENTED_REQUIREMENTS","title":"IMPLEMENTED_REQUIREMENTS","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent","title":" GenericByComponent (TrestleBaseModel) pydantic-model","text":"

                                                                            Generic ByComponent for SSP and DefinedComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            class GenericByComponent(TrestleBaseModel):\n\"\"\"Generic ByComponent for SSP and DefinedComponent.\"\"\"\n\n    # only in SSP\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003\n    ) = Field(\n        ...,\n        alias='component_uuid',\n        description='A machine-oriented identifier reference to the component that is implemeting a given control.',\n        title='Component Universally Unique Identifier Reference',\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='By-Component Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description=  # noqa E251\n        'An implementation statement that describes how a control or a control statement is implemented within the referenced system component.',  # noqa E501\n        title='Control Implementation Description',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[GenericSetParameter]] = Field(None, alias='set-parameters')\n    implementation_status: Optional[common.ImplementationStatus] = Field(None, alias='implementation-status')\n    # removed export, inherited, satisfied\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n\n    @staticmethod\n    def generate() -> GenericByComponent:\n\"\"\"Generate instance of generic ByComponent.\"\"\"\n        uuid = str(uuid4())\n        return GenericByComponent(component_uuid=const.SAMPLE_UUID_STR, uuid=uuid, description='')\n\n    def as_ssp(self) -> ossp.ByComponent:\n\"\"\"Convert to ssp format.\"\"\"\n        set_params = []\n        for set_param in as_list(self.set_parameters):\n            new_set_param = ossp.SetParameter(\n                param_id=set_param.param_id, values=set_param.values, remarks=set_param.remarks\n            )\n            set_params.append(new_set_param)\n        set_params = none_if_empty(set_params)\n        return ossp.ByComponent(\n            component_uuid=self.component_uuid,\n            uuid=self.uuid,\n            description=self.description,\n            props=self.props,\n            links=self.links,\n            set_parameters=set_params,\n            implementation_status=self.implementation_status,\n            responsible_roles=self.responsible_roles\n        )\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to the component that is implemeting a given control.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.description","title":"description: str pydantic-field required","text":"

                                                                            An implementation statement that describes how a control or a control statement is implemented within the referenced system component.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.implementation_status","title":"implementation_status: ImplementationStatus pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.set_parameters","title":"set_parameters: Optional[List[GenericSetParameter]] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.as_ssp","title":"as_ssp(self)","text":"

                                                                            Convert to ssp format.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            def as_ssp(self) -> ossp.ByComponent:\n\"\"\"Convert to ssp format.\"\"\"\n    set_params = []\n    for set_param in as_list(self.set_parameters):\n        new_set_param = ossp.SetParameter(\n            param_id=set_param.param_id, values=set_param.values, remarks=set_param.remarks\n        )\n        set_params.append(new_set_param)\n    set_params = none_if_empty(set_params)\n    return ossp.ByComponent(\n        component_uuid=self.component_uuid,\n        uuid=self.uuid,\n        description=self.description,\n        props=self.props,\n        links=self.links,\n        set_parameters=set_params,\n        implementation_status=self.implementation_status,\n        responsible_roles=self.responsible_roles\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericByComponent.generate","title":"generate() staticmethod","text":"

                                                                            Generate instance of generic ByComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @staticmethod\ndef generate() -> GenericByComponent:\n\"\"\"Generate instance of generic ByComponent.\"\"\"\n    uuid = str(uuid4())\n    return GenericByComponent(component_uuid=const.SAMPLE_UUID_STR, uuid=uuid, description='')\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent","title":" GenericComponent (TrestleBaseModel) pydantic-model","text":"

                                                                            Generic component for SSP SystemComponent and DefinedComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            class GenericComponent(TrestleBaseModel):\n\"\"\"Generic component for SSP SystemComponent and DefinedComponent.\"\"\"\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='Component Identifier',\n    )\n    type: constr(regex=r'^\\S(.*\\S)?$') = Field(  # noqa A003 F722\n        ...,\n        description='A category describing the purpose of the component.',\n        title='Component Type',\n    )\n    title: str = Field(\n        ...,\n        description='A human readable name for the component.',\n        title='Component Title',\n    )\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description',\n    )\n    purpose: Optional[str] = Field(\n        None,\n        description='A summary of the technological or business purpose of the component.',\n        title='Purpose',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    protocols: Optional[List[common.Protocol]] = Field(None)\n    # ssp does not have a list of ci's but it does have one ci\n    control_implementations: Optional[List[GenericControlImplementation]] = Field(None, alias='control-implementations')\n    remarks: Optional[str] = None\n    # ssp has\n    status: common.ImplementationStatus\n\n    def as_defined_component(self) -> comp.DefinedComponent:\n\"\"\"Convert to DefinedComponent.\"\"\"\n        status = self.status\n        class_dict = copy.deepcopy(self.__dict__)\n        class_dict.pop('status', None)\n        def_comp = comp.DefinedComponent(**class_dict)\n        ControlInterface.insert_status_in_props(def_comp, status)\n        return def_comp\n\n    @classmethod\n    def from_defined_component(cls, def_comp: comp.DefinedComponent) -> GenericComponent:\n\"\"\"Convert defined component to generic.\"\"\"\n        status = ControlInterface.get_status_from_props(def_comp)\n        class_dict = copy.deepcopy(def_comp.__dict__)\n        if 'control_implementations' in class_dict:\n            new_cis = []\n            for ci in class_dict['control_implementations']:\n                new_cis.append(GenericControlImplementation.from_component_ci(ci))\n            class_dict['control-implementations'] = new_cis\n            class_dict.pop('control_implementations', None)\n        class_dict['status'] = status\n        return cls(**class_dict)\n\n    def as_system_component(self, status_override: str = '') -> ossp.SystemComponent:\n\"\"\"Convert to SystemComponent.\"\"\"\n        class_dict = copy.deepcopy(self.__dict__)\n        class_dict.pop('control_implementations', None)\n        status_str = self.status.state if self.status else const.STATUS_OPERATIONAL\n        status_str = status_override if status_override else status_str\n        if status_str not in ['under-development', 'operational', 'disposition', 'other']:\n            logger.warning(\n                f'SystemComponent status {status_str} not recognized.  Setting to {const.STATUS_OPERATIONAL}'\n            )\n            status_str = const.STATUS_OPERATIONAL\n        class_dict['status'] = ossp.Status(state=status_str, remarks=self.status.remarks)\n        return ossp.SystemComponent(**class_dict)\n\n    @staticmethod\n    def generate() -> GenericComponent:\n\"\"\"Generate instance of GenericComponent.\"\"\"\n        uuid = str(uuid4())\n        status = common.ImplementationStatus(state=const.STATUS_OPERATIONAL)\n        return GenericComponent(uuid=uuid, type=const.REPLACE_ME, title='', description='', status=status)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.control_implementations","title":"control_implementations: List[trestle.core.generic_oscal.GenericControlImplementation] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.description","title":"description: str pydantic-field required","text":"

                                                                            A description of the component, including information about its function.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.protocols","title":"protocols: List[trestle.oscal.common.Protocol] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.purpose","title":"purpose: str pydantic-field","text":"

                                                                            A summary of the technological or business purpose of the component.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.status","title":"status: ImplementationStatus pydantic-field required","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.title","title":"title: str pydantic-field required","text":"

                                                                            A human readable name for the component.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.type","title":"type: ConstrainedStrValue pydantic-field required","text":"

                                                                            A category describing the purpose of the component.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.as_defined_component","title":"as_defined_component(self)","text":"

                                                                            Convert to DefinedComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            def as_defined_component(self) -> comp.DefinedComponent:\n\"\"\"Convert to DefinedComponent.\"\"\"\n    status = self.status\n    class_dict = copy.deepcopy(self.__dict__)\n    class_dict.pop('status', None)\n    def_comp = comp.DefinedComponent(**class_dict)\n    ControlInterface.insert_status_in_props(def_comp, status)\n    return def_comp\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.as_system_component","title":"as_system_component(self, status_override='')","text":"

                                                                            Convert to SystemComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            def as_system_component(self, status_override: str = '') -> ossp.SystemComponent:\n\"\"\"Convert to SystemComponent.\"\"\"\n    class_dict = copy.deepcopy(self.__dict__)\n    class_dict.pop('control_implementations', None)\n    status_str = self.status.state if self.status else const.STATUS_OPERATIONAL\n    status_str = status_override if status_override else status_str\n    if status_str not in ['under-development', 'operational', 'disposition', 'other']:\n        logger.warning(\n            f'SystemComponent status {status_str} not recognized.  Setting to {const.STATUS_OPERATIONAL}'\n        )\n        status_str = const.STATUS_OPERATIONAL\n    class_dict['status'] = ossp.Status(state=status_str, remarks=self.status.remarks)\n    return ossp.SystemComponent(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.from_defined_component","title":"from_defined_component(def_comp) classmethod","text":"

                                                                            Convert defined component to generic.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @classmethod\ndef from_defined_component(cls, def_comp: comp.DefinedComponent) -> GenericComponent:\n\"\"\"Convert defined component to generic.\"\"\"\n    status = ControlInterface.get_status_from_props(def_comp)\n    class_dict = copy.deepcopy(def_comp.__dict__)\n    if 'control_implementations' in class_dict:\n        new_cis = []\n        for ci in class_dict['control_implementations']:\n            new_cis.append(GenericControlImplementation.from_component_ci(ci))\n        class_dict['control-implementations'] = new_cis\n        class_dict.pop('control_implementations', None)\n    class_dict['status'] = status\n    return cls(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericComponent.generate","title":"generate() staticmethod","text":"

                                                                            Generate instance of GenericComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @staticmethod\ndef generate() -> GenericComponent:\n\"\"\"Generate instance of GenericComponent.\"\"\"\n    uuid = str(uuid4())\n    status = common.ImplementationStatus(state=const.STATUS_OPERATIONAL)\n    return GenericComponent(uuid=uuid, type=const.REPLACE_ME, title='', description='', status=status)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation","title":" GenericControlImplementation (TrestleBaseModel) pydantic-model","text":"

                                                                            Generic control implementation for SSP and CompDef.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            class GenericControlImplementation(TrestleBaseModel):\n\"\"\"Generic control implementation for SSP and CompDef.\"\"\"\n\n    # not in ssp\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a set of implemented controls elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation set can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='Control Implementation Set Identifier',\n    )\n    # not in ssp\n    source: str = Field(\n        ...,\n        description=  # noqa E251\n        'A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.',  # noqa E501\n        title='Source Resource Reference',\n    )\n    description: str = Field(\n        ...,\n        description=  # noqa E251\n        'A description of how the specified set of controls are implemented for the containing component or capability.',  # noqa E501\n        title='Control Implementation Description',\n    )\n    # not in ssp\n    props: Optional[List[common.Property]] = Field(None)\n    # not in ssp\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[GenericSetParameter]] = Field(None, alias='set-parameters')\n    implemented_requirements: List[GenericImplementedRequirement] = Field(..., alias='implemented-requirements')\n\n    @staticmethod\n    def generate() -> GenericControlImplementation:\n\"\"\"Generate instance of this class.\"\"\"\n        uuid = str(uuid4())\n        imp_reqs = [GenericImplementedRequirement.generate()]\n        class_dict = {\n            'uuid': uuid,\n            'control-id': const.REPLACE_ME,\n            'source': const.REPLACE_ME,\n            'description': '',\n            'implemented-requirements': imp_reqs\n        }\n        return GenericControlImplementation(**class_dict)\n\n    @classmethod\n    def from_component_ci(cls, control_imp: comp.ControlImplementation) -> GenericControlImplementation:\n\"\"\"Convert component control imp to generic.\"\"\"\n        class_dict = copy.deepcopy(control_imp.__dict__)\n        if IMPLEMENTED_REQUIREMENTS in class_dict:\n            new_irs = []\n            ir_list = class_dict.get(IMPLEMENTED_REQUIREMENTS, None)\n            for ir in as_list(ir_list):\n                new_ir = GenericImplementedRequirement.from_comp_def(ir)\n                new_irs.append(new_ir)\n            class_dict['implemented-requirements'] = none_if_empty(new_irs)\n            class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n            new_sps = []\n            sp_list = class_dict.get('set_parameters', None)\n            for sp in as_list(sp_list):\n                new_sps.append(GenericSetParameter.from_defined_component(sp))\n            class_dict['set-parameters'] = none_if_empty(new_sps)\n            class_dict.pop('set_parameters', None)\n\n        return cls(**class_dict)\n\n    def as_ssp(self) -> ossp.ControlImplementation:\n\"\"\"Represent in ssp form.\"\"\"\n        imp_reqs = []\n        for imp_req in self.implemented_requirements:\n            imp_reqs.append(imp_req.as_ssp())\n        class_dict = self.__dict__\n        for prop in ['uuid', 'source', 'props', 'links', IMPLEMENTED_REQUIREMENTS]:\n            class_dict.pop(prop, None)\n        if imp_reqs:\n            class_dict['implemented-requirements'] = imp_reqs\n            class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n        return ossp.ControlImplementation(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.description","title":"description: str pydantic-field required","text":"

                                                                            A description of how the specified set of controls are implemented for the containing component or capability.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.implemented_requirements","title":"implemented_requirements: List[trestle.core.generic_oscal.GenericImplementedRequirement] pydantic-field required","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.set_parameters","title":"set_parameters: List[trestle.core.generic_oscal.GenericSetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.source","title":"source: str pydantic-field required","text":"

                                                                            A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a set of implemented controls elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation set can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.as_ssp","title":"as_ssp(self)","text":"

                                                                            Represent in ssp form.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            def as_ssp(self) -> ossp.ControlImplementation:\n\"\"\"Represent in ssp form.\"\"\"\n    imp_reqs = []\n    for imp_req in self.implemented_requirements:\n        imp_reqs.append(imp_req.as_ssp())\n    class_dict = self.__dict__\n    for prop in ['uuid', 'source', 'props', 'links', IMPLEMENTED_REQUIREMENTS]:\n        class_dict.pop(prop, None)\n    if imp_reqs:\n        class_dict['implemented-requirements'] = imp_reqs\n        class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n    return ossp.ControlImplementation(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.from_component_ci","title":"from_component_ci(control_imp) classmethod","text":"

                                                                            Convert component control imp to generic.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @classmethod\ndef from_component_ci(cls, control_imp: comp.ControlImplementation) -> GenericControlImplementation:\n\"\"\"Convert component control imp to generic.\"\"\"\n    class_dict = copy.deepcopy(control_imp.__dict__)\n    if IMPLEMENTED_REQUIREMENTS in class_dict:\n        new_irs = []\n        ir_list = class_dict.get(IMPLEMENTED_REQUIREMENTS, None)\n        for ir in as_list(ir_list):\n            new_ir = GenericImplementedRequirement.from_comp_def(ir)\n            new_irs.append(new_ir)\n        class_dict['implemented-requirements'] = none_if_empty(new_irs)\n        class_dict.pop(IMPLEMENTED_REQUIREMENTS, None)\n        new_sps = []\n        sp_list = class_dict.get('set_parameters', None)\n        for sp in as_list(sp_list):\n            new_sps.append(GenericSetParameter.from_defined_component(sp))\n        class_dict['set-parameters'] = none_if_empty(new_sps)\n        class_dict.pop('set_parameters', None)\n\n    return cls(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericControlImplementation.generate","title":"generate() staticmethod","text":"

                                                                            Generate instance of this class.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @staticmethod\ndef generate() -> GenericControlImplementation:\n\"\"\"Generate instance of this class.\"\"\"\n    uuid = str(uuid4())\n    imp_reqs = [GenericImplementedRequirement.generate()]\n    class_dict = {\n        'uuid': uuid,\n        'control-id': const.REPLACE_ME,\n        'source': const.REPLACE_ME,\n        'description': '',\n        'implemented-requirements': imp_reqs\n    }\n    return GenericControlImplementation(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement","title":" GenericImplementedRequirement (TrestleBaseModel) pydantic-model","text":"

                                                                            Generic ImplementedRequirement for SSP and DefinedComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            class GenericImplementedRequirement(TrestleBaseModel):\n\"\"\"Generic ImplementedRequirement for SSP and DefinedComponent.\"\"\"\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a specific control implementation elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',  # noqa E501\n        title='Control Implementation Identifier',\n    )\n    control_id: constr(\n        regex=  # noqa E251\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'  # noqa E501\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=  # noqa E251\n        'A human-oriented identifier reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',  # noqa E501\n        title='Control Identifier Reference',\n    )\n    # only compdef has description\n    description: str = Field(\n        ...,\n        description=  # noqa E251\n        'A description of how the specified control is implemented for the containing component or capability.',  # noqa E501\n        title='Control Implementation Description',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[GenericSetParameter]] = Field(None, alias='set-parameters')\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    statements: Optional[List[GenericStatement]] = Field(None)\n    remarks: Optional[str] = None\n    # ssp has following\n    by_components: Optional[List[GenericByComponent]] = Field(None, alias='by-components')\n\n    @staticmethod\n    def generate() -> GenericImplementedRequirement:\n\"\"\"Generate instance of this class.\"\"\"\n        uuid = str(uuid4())\n        class_dict = {'uuid': uuid, 'control-id': const.REPLACE_ME, 'description': ''}\n        return GenericImplementedRequirement(**class_dict)\n\n    @classmethod\n    def from_comp_def(cls, imp_req: comp.ImplementedRequirement) -> GenericImplementedRequirement:\n\"\"\"Convert component form of imp req to generic.\"\"\"\n        class_dict = copy.deepcopy(imp_req.__dict__)\n        class_dict['control-id'] = class_dict.pop('control_id', None)\n        return cls(**class_dict)\n\n    def as_ssp(self) -> ossp.ImplementedRequirement:\n\"\"\"Convert to ssp form.\"\"\"\n        class_dict = copy.deepcopy(self.__dict__)\n        del class_dict['description']\n        new_stat_list = []\n        for statement in as_list(self.statements):\n            new_stat_list.append(statement.as_ssp())\n        if new_stat_list:\n            class_dict['statements'] = new_stat_list\n        return ossp.ImplementedRequirement(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.by_components","title":"by_components: List[trestle.core.generic_oscal.GenericByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented identifier reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.description","title":"description: str pydantic-field required","text":"

                                                                            A description of how the specified control is implemented for the containing component or capability.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.set_parameters","title":"set_parameters: List[trestle.core.generic_oscal.GenericSetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.statements","title":"statements: List[trestle.core.generic_oscal.GenericStatement] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference a specific control implementation elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.as_ssp","title":"as_ssp(self)","text":"

                                                                            Convert to ssp form.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            def as_ssp(self) -> ossp.ImplementedRequirement:\n\"\"\"Convert to ssp form.\"\"\"\n    class_dict = copy.deepcopy(self.__dict__)\n    del class_dict['description']\n    new_stat_list = []\n    for statement in as_list(self.statements):\n        new_stat_list.append(statement.as_ssp())\n    if new_stat_list:\n        class_dict['statements'] = new_stat_list\n    return ossp.ImplementedRequirement(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.from_comp_def","title":"from_comp_def(imp_req) classmethod","text":"

                                                                            Convert component form of imp req to generic.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @classmethod\ndef from_comp_def(cls, imp_req: comp.ImplementedRequirement) -> GenericImplementedRequirement:\n\"\"\"Convert component form of imp req to generic.\"\"\"\n    class_dict = copy.deepcopy(imp_req.__dict__)\n    class_dict['control-id'] = class_dict.pop('control_id', None)\n    return cls(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericImplementedRequirement.generate","title":"generate() staticmethod","text":"

                                                                            Generate instance of this class.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @staticmethod\ndef generate() -> GenericImplementedRequirement:\n\"\"\"Generate instance of this class.\"\"\"\n    uuid = str(uuid4())\n    class_dict = {'uuid': uuid, 'control-id': const.REPLACE_ME, 'description': ''}\n    return GenericImplementedRequirement(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter","title":" GenericSetParameter (TrestleBaseModel) pydantic-model","text":"

                                                                            Generic SetParameter for SSP and DefinedComponent.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            class GenericSetParameter(TrestleBaseModel):\n\"\"\"Generic SetParameter for SSP and DefinedComponent.\"\"\"\n\n    param_id: constr(\n        regex=  # noqa E251\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'  # noqa E501\n    ) = Field(\n        ...,\n        alias='param-id',\n        description=  # noqa E251\n        \"A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.\",  # noqa E501\n        title='Parameter ID',\n    )\n    values: List[str] = Field(...)\n    remarks: Optional[str] = None\n\n    @staticmethod\n    def from_defined_component(sp: comp.SetParameter):\n\"\"\"Generate generic set parameter from comp_def version.\"\"\"\n        class_dict = {'param-id': sp.param_id, 'values': sp.values, 'remarks': sp.remarks}\n        return GenericSetParameter(**class_dict)\n\n    def to_ssp(self):\n\"\"\"Convert to ssp format.\"\"\"\n        return (ossp.SetParameter(param_id=self.param_id, values=self.values, remarks=self.remarks))\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.values","title":"values: List[str] pydantic-field required","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.from_defined_component","title":"from_defined_component(sp) staticmethod","text":"

                                                                            Generate generic set parameter from comp_def version.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            @staticmethod\ndef from_defined_component(sp: comp.SetParameter):\n\"\"\"Generate generic set parameter from comp_def version.\"\"\"\n    class_dict = {'param-id': sp.param_id, 'values': sp.values, 'remarks': sp.remarks}\n    return GenericSetParameter(**class_dict)\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericSetParameter.to_ssp","title":"to_ssp(self)","text":"

                                                                            Convert to ssp format.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            def to_ssp(self):\n\"\"\"Convert to ssp format.\"\"\"\n    return (ossp.SetParameter(param_id=self.param_id, values=self.values, remarks=self.remarks))\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement","title":" GenericStatement (TrestleBaseModel) pydantic-model","text":"

                                                                            Generic statement for SSP and DefinedComp.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            class GenericStatement(TrestleBaseModel):\n\"\"\"Generic statement for SSP and DefinedComp.\"\"\"\n\n    statement_id: constr(\n        regex=  # noqa E251\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'  # noqa FS003 E501\n    ) = Field(\n        ...,\n        alias='statement_id',\n        description='A human-oriented identifier reference to a control statement.',\n        title='Control Statement Reference',\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'  # noqa FS003 F722\n    ) = Field(\n        ...,\n        description=  # noqa E251\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).',  # noqa E501\n        title='Control Statement Reference Universally Unique Identifier',\n    )\n    # this is not in ssp statement\n    description: str = Field(\n        ...,\n        description='A summary of how the containing control statement is implemented by the component or capability.',\n        title='Statement Implementation Description',\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n    # ssp has following\n    by_components: Optional[List[GenericByComponent]] = Field(None, alias='by-components')\n\n    def as_ssp(self) -> ossp.Statement:\n\"\"\"Represent in ssp form.\"\"\"\n        class_dict = copy.deepcopy(self.__dict__)\n        class_dict.pop('description', None)\n        by_comps = []\n        for by_comp in as_list(self.by_components):\n            new_by_comp = by_comp.as_ssp()\n            by_comps.append(new_by_comp)\n        return ossp.Statement(\n            statement_id=self.statement_id,\n            uuid=self.uuid,\n            props=self.props,\n            links=self.links,\n            responsible_roles=self.responsible_roles,\n            by_components=by_comps,\n            remarks=self.remarks\n        )\n
                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.by_components","title":"by_components: List[trestle.core.generic_oscal.GenericByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of how the containing control statement is implemented by the component or capability.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.statement_id","title":"statement_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented identifier reference to a control statement.

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).

                                                                            "},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.generic_oscal/#trestle.core.generic_oscal.GenericStatement.as_ssp","title":"as_ssp(self)","text":"

                                                                            Represent in ssp form.

                                                                            Source code in trestle/core/generic_oscal.py
                                                                            def as_ssp(self) -> ossp.Statement:\n\"\"\"Represent in ssp form.\"\"\"\n    class_dict = copy.deepcopy(self.__dict__)\n    class_dict.pop('description', None)\n    by_comps = []\n    for by_comp in as_list(self.by_components):\n        new_by_comp = by_comp.as_ssp()\n        by_comps.append(new_by_comp)\n    return ossp.Statement(\n        statement_id=self.statement_id,\n        uuid=self.uuid,\n        props=self.props,\n        links=self.links,\n        responsible_roles=self.responsible_roles,\n        by_components=by_comps,\n        remarks=self.remarks\n    )\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/","title":"jinja","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja","title":"trestle.core.jinja","text":"

                                                                            Trestle utilities to customize .

                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude","title":" MDCleanInclude (TrestleJinjaExtension) ","text":"

                                                                            Inject the parameter of the tag as the resulting content.

                                                                            Source code in trestle/core/jinja.py
                                                                            class MDCleanInclude(TrestleJinjaExtension):\n\"\"\"Inject the parameter of the tag as the resulting content.\"\"\"\n\n    tags = {'md_clean_include'}\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n        kwargs = None\n        expected_heading_level = None\n        count = 0\n        while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n            count = count + 1\n            if count > self.max_tag_parse:\n                raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n            token = parser.stream.current\n            if token.test('name:md_clean_include'):\n                parser.stream.expect(lexer.TOKEN_NAME)\n                markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n            elif kwargs is not None:\n                arg = token.value\n                next(parser.stream)\n                parser.stream.expect(lexer.TOKEN_ASSIGN)\n                token = parser.stream.current\n                exp = self.parse_expression(parser)\n                kwargs[arg] = exp.value\n            else:\n                if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                    kwargs = {}\n                continue\n        md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n        fm = frontmatter.loads(md_content)\n        content = fm.content\n        content += '\\n\\n'\n        if kwargs is not None:\n            expected_heading_level = kwargs.get('heading_level')\n        if expected_heading_level is not None:\n            content = adjust_heading_level(content, expected_heading_level)\n\n        local_parser = Parser(self.environment, content)\n        top_level_output = local_parser.parse()\n\n        return top_level_output.body\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.tags","title":"tags: Set[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.__init__","title":"__init__(self, environment) special","text":"Source code in trestle/core/jinja.py
                                                                            def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDCleanInclude.parse","title":"parse(self, parser)","text":"

                                                                            Execute parsing of md token and return nodes.

                                                                            Source code in trestle/core/jinja.py
                                                                            def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n    kwargs = None\n    expected_heading_level = None\n    count = 0\n    while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n        count = count + 1\n        if count > self.max_tag_parse:\n            raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n        token = parser.stream.current\n        if token.test('name:md_clean_include'):\n            parser.stream.expect(lexer.TOKEN_NAME)\n            markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n        elif kwargs is not None:\n            arg = token.value\n            next(parser.stream)\n            parser.stream.expect(lexer.TOKEN_ASSIGN)\n            token = parser.stream.current\n            exp = self.parse_expression(parser)\n            kwargs[arg] = exp.value\n        else:\n            if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                kwargs = {}\n            continue\n    md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n    fm = frontmatter.loads(md_content)\n    content = fm.content\n    content += '\\n\\n'\n    if kwargs is not None:\n        expected_heading_level = kwargs.get('heading_level')\n    if expected_heading_level is not None:\n        content = adjust_heading_level(content, expected_heading_level)\n\n    local_parser = Parser(self.environment, content)\n    top_level_output = local_parser.parse()\n\n    return top_level_output.body\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp","title":" MDDatestamp (TrestleJinjaExtension) ","text":"

                                                                            Inject the parameter of the tag as the resulting content.

                                                                            Source code in trestle/core/jinja.py
                                                                            class MDDatestamp(TrestleJinjaExtension):\n\"\"\"Inject the parameter of the tag as the resulting content.\"\"\"\n\n    tags = {'md_datestamp'}\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n        kwargs = None\n        count = 0\n        while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n            count = count + 1\n            token = parser.stream.current\n            if count > self.max_tag_parse:\n                raise err.TrestleError(f'Unexpected Jinja tag structure provided at token {token.value}')\n            if token.test('name:md_datestamp'):\n                parser.stream.expect(lexer.TOKEN_NAME)\n            elif kwargs is not None:\n                arg = token.value\n                next(parser.stream)\n                parser.stream.expect(lexer.TOKEN_ASSIGN)\n                token = parser.stream.current\n                exp = self.parse_expression(parser)\n                kwargs[arg] = exp.value\n            else:\n                if parser.stream.look().type == lexer.TOKEN_ASSIGN or parser.stream.look().type == lexer.TOKEN_STRING:\n                    kwargs = {}\n                continue\n\n        if kwargs is not None:\n            if 'format' in kwargs and type(kwargs['format'] is str):\n                date_string = date.today().strftime(kwargs['format'])\n            else:\n                date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT)\n            if 'newline' in kwargs and kwargs['newline'] is False:\n                pass\n            else:\n                date_string += '\\n\\n'\n        else:\n            date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT) + '\\n\\n'\n\n        local_parser = Parser(self.environment, date_string)\n        datestamp_output = local_parser.parse()\n\n        return datestamp_output.body\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.tags","title":"tags: Set[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.__init__","title":"__init__(self, environment) special","text":"Source code in trestle/core/jinja.py
                                                                            def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDDatestamp.parse","title":"parse(self, parser)","text":"

                                                                            Execute parsing of md token and return nodes.

                                                                            Source code in trestle/core/jinja.py
                                                                            def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n    kwargs = None\n    count = 0\n    while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n        count = count + 1\n        token = parser.stream.current\n        if count > self.max_tag_parse:\n            raise err.TrestleError(f'Unexpected Jinja tag structure provided at token {token.value}')\n        if token.test('name:md_datestamp'):\n            parser.stream.expect(lexer.TOKEN_NAME)\n        elif kwargs is not None:\n            arg = token.value\n            next(parser.stream)\n            parser.stream.expect(lexer.TOKEN_ASSIGN)\n            token = parser.stream.current\n            exp = self.parse_expression(parser)\n            kwargs[arg] = exp.value\n        else:\n            if parser.stream.look().type == lexer.TOKEN_ASSIGN or parser.stream.look().type == lexer.TOKEN_STRING:\n                kwargs = {}\n            continue\n\n    if kwargs is not None:\n        if 'format' in kwargs and type(kwargs['format'] is str):\n            date_string = date.today().strftime(kwargs['format'])\n        else:\n            date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT)\n        if 'newline' in kwargs and kwargs['newline'] is False:\n            pass\n        else:\n            date_string += '\\n\\n'\n    else:\n        date_string = date.today().strftime(markdown_const.JINJA_DATESTAMP_FORMAT) + '\\n\\n'\n\n    local_parser = Parser(self.environment, date_string)\n    datestamp_output = local_parser.parse()\n\n    return datestamp_output.body\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude","title":" MDSectionInclude (TrestleJinjaExtension) ","text":"

                                                                            Inject the parameter of the tag as the resulting content.

                                                                            Source code in trestle/core/jinja.py
                                                                            class MDSectionInclude(TrestleJinjaExtension):\n\"\"\"Inject the parameter of the tag as the resulting content.\"\"\"\n\n    tags = {'mdsection_include'}\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n        kwargs = None\n        expected_heading_level = None\n        count = 0\n        while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n            count = count + 1\n            if count > self.max_tag_parse:\n                raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n            token = parser.stream.current\n            if token.test('name:mdsection_include'):\n                parser.stream.expect(lexer.TOKEN_NAME)\n                markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n                section_title = parser.stream.expect(lexer.TOKEN_STRING)\n            elif kwargs is not None:\n                arg = token.value\n                next(parser.stream)\n                parser.stream.expect(lexer.TOKEN_ASSIGN)\n                token = parser.stream.current\n                exp = self.parse_expression(parser)\n                kwargs[arg] = exp.value\n            else:\n                if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                    kwargs = {}\n                continue\n        # Use the established environment to source the file\n        md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n        fm = frontmatter.loads(md_content)\n        if not fm.metadata == {}:\n            logger.warning('Non zero metadata on MD section include - ignoring')\n        full_md = docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown(fm.content.split('\\n'))\n        md_section = full_md.get_node_for_key(section_title.value, strict_matching=True)\n        # adjust\n        if kwargs is not None:\n            expected_heading_level = kwargs.get('heading_level')\n        if expected_heading_level is not None:\n            level = md_section.get_node_header_lvl()\n            delta = int(expected_heading_level) - level\n            if not delta == 0:\n                md_section.change_header_level_by(delta)\n        if not md_section:\n            raise err.TrestleError(\n                f'Unable to retrieve section \"{section_title.value}\"\" from {markdown_source.value} jinja template.'\n            )\n        local_parser = Parser(self.environment, md_section.content.raw_text)\n        top_level_output = local_parser.parse()\n\n        return top_level_output.body\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.tags","title":"tags: Set[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.__init__","title":"__init__(self, environment) special","text":"Source code in trestle/core/jinja.py
                                                                            def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.MDSectionInclude.parse","title":"parse(self, parser)","text":"

                                                                            Execute parsing of md token and return nodes.

                                                                            Source code in trestle/core/jinja.py
                                                                            def parse(self, parser):\n\"\"\"Execute parsing of md token and return nodes.\"\"\"\n    kwargs = None\n    expected_heading_level = None\n    count = 0\n    while parser.stream.current.type != lexer.TOKEN_BLOCK_END:\n        count = count + 1\n        if count > self.max_tag_parse:\n            raise err.TrestleError('Unexpected Jinja tag structure provided, please review docs.')\n        token = parser.stream.current\n        if token.test('name:mdsection_include'):\n            parser.stream.expect(lexer.TOKEN_NAME)\n            markdown_source = parser.stream.expect(lexer.TOKEN_STRING)\n            section_title = parser.stream.expect(lexer.TOKEN_STRING)\n        elif kwargs is not None:\n            arg = token.value\n            next(parser.stream)\n            parser.stream.expect(lexer.TOKEN_ASSIGN)\n            token = parser.stream.current\n            exp = self.parse_expression(parser)\n            kwargs[arg] = exp.value\n        else:\n            if parser.stream.look().type == lexer.TOKEN_ASSIGN:\n                kwargs = {}\n            continue\n    # Use the established environment to source the file\n    md_content, _, _ = self.environment.loader.get_source(self.environment, markdown_source.value)\n    fm = frontmatter.loads(md_content)\n    if not fm.metadata == {}:\n        logger.warning('Non zero metadata on MD section include - ignoring')\n    full_md = docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown(fm.content.split('\\n'))\n    md_section = full_md.get_node_for_key(section_title.value, strict_matching=True)\n    # adjust\n    if kwargs is not None:\n        expected_heading_level = kwargs.get('heading_level')\n    if expected_heading_level is not None:\n        level = md_section.get_node_header_lvl()\n        delta = int(expected_heading_level) - level\n        if not delta == 0:\n            md_section.change_header_level_by(delta)\n    if not md_section:\n        raise err.TrestleError(\n            f'Unable to retrieve section \"{section_title.value}\"\" from {markdown_source.value} jinja template.'\n        )\n    local_parser = Parser(self.environment, md_section.content.raw_text)\n    top_level_output = local_parser.parse()\n\n    return top_level_output.body\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension","title":" TrestleJinjaExtension (Extension) ","text":"

                                                                            Class to define common methods to be inherited from for use in trestle.

                                                                            Source code in trestle/core/jinja.py
                                                                            class TrestleJinjaExtension(Extension):\n\"\"\"Class to define common methods to be inherited from for use in trestle.\"\"\"\n\n    # This\n    max_tag_parse = 20\n\n    def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n        super().__init__(environment)\n\n    @staticmethod\n    def parse_expression(parser):\n\"\"\"Safely parse jinja expression.\"\"\"\n        # Licensed under MIT from:\n        # https://github.com/MoritzS/jinja2-django-tags/blob/master/jdj_tags/extensions.py#L424\n        # Due to how the jinja2 parser works, it treats \"foo\" \"bar\" as a single\n        # string literal as it is the case in python.\n        # But the url tag in django supports multiple string arguments, e.g.\n        # \"{% url 'my_view' 'arg1' 'arg2' %}\".\n        # That's why we have to check if it's a string literal first.\n        token = parser.stream.current\n        if token.test(lexer.TOKEN_STRING):\n            expr = nodes.Const(token.value, lineno=token.lineno)\n            next(parser.stream)\n        else:\n            expr = parser.parse_expression(False)\n\n        return expr\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.identifier","title":"identifier: ClassVar[str]","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.max_tag_parse","title":"max_tag_parse","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.__init__","title":"__init__(self, environment) special","text":"

                                                                            Ensure enviroment is set and carried into class vars.

                                                                            Source code in trestle/core/jinja.py
                                                                            def __init__(self, environment: Environment) -> None:\n\"\"\"Ensure enviroment is set and carried into class vars.\"\"\"\n    super().__init__(environment)\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.TrestleJinjaExtension.parse_expression","title":"parse_expression(parser) staticmethod","text":"

                                                                            Safely parse jinja expression.

                                                                            Source code in trestle/core/jinja.py
                                                                            @staticmethod\ndef parse_expression(parser):\n\"\"\"Safely parse jinja expression.\"\"\"\n    # Licensed under MIT from:\n    # https://github.com/MoritzS/jinja2-django-tags/blob/master/jdj_tags/extensions.py#L424\n    # Due to how the jinja2 parser works, it treats \"foo\" \"bar\" as a single\n    # string literal as it is the case in python.\n    # But the url tag in django supports multiple string arguments, e.g.\n    # \"{% url 'my_view' 'arg1' 'arg2' %}\".\n    # That's why we have to check if it's a string literal first.\n    token = parser.stream.current\n    if token.test(lexer.TOKEN_STRING):\n        expr = nodes.Const(token.value, lineno=token.lineno)\n        next(parser.stream)\n    else:\n        expr = parser.parse_expression(False)\n\n    return expr\n
                                                                            "},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.jinja/#trestle.core.jinja.adjust_heading_level","title":"adjust_heading_level(input_md, expected)","text":"

                                                                            Adjust the header level of a markdown string such that the most significant header matches the expected #'s.

                                                                            Source code in trestle/core/jinja.py
                                                                            def adjust_heading_level(input_md: str, expected: int) -> str:\n\"\"\"Adjust the header level of a markdown string such that the most significant header matches the expected #'s.\"\"\"\n    output_md = input_md\n    mdn = docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown(input_md.split('\\n'))\n    if mdn.subnodes:\n        mdn_top_heading = mdn.subnodes[0].get_node_header_lvl()\n        delta = int(expected) - mdn_top_heading\n        if not delta == 0:\n            mdn.change_header_level_by(delta)\n            output_md = mdn.content.raw_text\n    return output_md\n
                                                                            "},{"location":"api_reference/trestle.core.links_validator/","title":"links_validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator","title":"trestle.core.links_validator","text":"

                                                                            Validate catalog by confirming control links match resources in backmatter.

                                                                            "},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.LinksValidator","title":" LinksValidator (Validator) ","text":"

                                                                            Validator to confirm all uuids in links and prose match resources in backmatter.

                                                                            Source code in trestle/core/links_validator.py
                                                                            class LinksValidator(Validator):\n\"\"\"Validator to confirm all uuids in links and prose match resources in backmatter.\"\"\"\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            Always returns True, but gives warning if links and resources are not one-to-one.\n        \"\"\"\n        refs = ModelUtils.find_uuid_refs(model)\n\n        # find uuids in backmatter\n        links: List[str] = []\n        if model.back_matter and model.back_matter.resources:\n            links = [res.uuid for res in model.back_matter.resources]\n            seen: Set[str] = set()\n            dupes: List[str] = []\n            for uuid in links:\n                if uuid in seen:\n                    dupes.append(uuid)\n                else:\n                    seen.add(uuid)\n            if dupes:\n                if not quiet:\n                    logger.warning(f'Backmatter has  {len(dupes)} duplicate link uuids.')\n                logger.debug(f'Backmatter has {len(dupes)} duplicate link uuids: {dupes}')\n\n        links = set(links)\n        in_refs = refs.difference(links)\n        if in_refs:\n            if not quiet:\n                logger.warning(f'Model references {len(refs)} uuids and {len(in_refs)} of them are not in resources.')\n            logger.debug(f'Model references {len(in_refs)} uuids not in resources: {in_refs}')\n\n        in_links = links.difference(refs)\n        if in_links:\n            if not quiet:\n                logger.warning(f'Resources have {len(links)} uuids and {len(in_links)} are not referenced by model.')\n            logger.debug(f'Resources have {len(in_links)} uuids not referenced by model: {in_links}')\n\n        # This validator is intended just to give warnings, so it always returns True\n        return True\n
                                                                            "},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.LinksValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.links_validator/#trestle.core.links_validator.LinksValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                                                            Test if the model is valid.

                                                                            Parameters:

                                                                            Name Type Description Default model ~TopLevelOscalModel

                                                                            A top level OSCAL model.

                                                                            required quiet bool

                                                                            Don't report msgs unless invalid.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            Always returns True, but gives warning if links and resources are not one-to-one.

                                                                            Source code in trestle/core/links_validator.py
                                                                            def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        Always returns True, but gives warning if links and resources are not one-to-one.\n    \"\"\"\n    refs = ModelUtils.find_uuid_refs(model)\n\n    # find uuids in backmatter\n    links: List[str] = []\n    if model.back_matter and model.back_matter.resources:\n        links = [res.uuid for res in model.back_matter.resources]\n        seen: Set[str] = set()\n        dupes: List[str] = []\n        for uuid in links:\n            if uuid in seen:\n                dupes.append(uuid)\n            else:\n                seen.add(uuid)\n        if dupes:\n            if not quiet:\n                logger.warning(f'Backmatter has  {len(dupes)} duplicate link uuids.')\n            logger.debug(f'Backmatter has {len(dupes)} duplicate link uuids: {dupes}')\n\n    links = set(links)\n    in_refs = refs.difference(links)\n    if in_refs:\n        if not quiet:\n            logger.warning(f'Model references {len(refs)} uuids and {len(in_refs)} of them are not in resources.')\n        logger.debug(f'Model references {len(in_refs)} uuids not in resources: {in_refs}')\n\n    in_links = links.difference(refs)\n    if in_links:\n        if not quiet:\n            logger.warning(f'Resources have {len(links)} uuids and {len(in_links)} are not referenced by model.')\n        logger.debug(f'Resources have {len(in_links)} uuids not referenced by model: {in_links}')\n\n    # This validator is intended just to give warnings, so it always returns True\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/","title":"base_markdown_node","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node","title":"trestle.core.markdown.base_markdown_node","text":"

                                                                            A base markdown node.

                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode","title":" BaseMarkdownNode ","text":"

                                                                            Markdown will be read to the tree.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            class BaseMarkdownNode:\n\"\"\"Markdown will be read to the tree.\"\"\"\n\n    def __init__(self, key: str, content: BaseSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n        self.subnodes: List[BaseMarkdownNode] = []\n        self.key = key\n        self.content = content\n        self.starting_line = starting_line\n\n    @classmethod\n    def build_tree_from_markdown(cls, lines: List[str]) -> BaseMarkdownNode:\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n        ob = cls.__new__(cls)\n        start_level = ob._get_max_header_lvl(lines)\n        ob, _ = ob._build_tree(lines, 'root', 0, start_level)\n        return ob\n\n    def get_all_headers_for_level(self, level: int) -> Iterable[str]:\n\"\"\"Return all headers per specified level of hierarchy.\"\"\"\n        return list(\n            filter(lambda header: self._get_header_level_if_valid(header) == level, self.content.subnodes_keys)\n        ).__iter__()\n\n    def get_node_for_key(self, key: str, strict_matching: bool = True) -> Optional[BaseMarkdownNode]:\n\"\"\"Return a first node for the given key, substring matching is supported. The method is case insensitive.\"\"\"\n        if not strict_matching:\n            if not any(key.lower() in el.lower() for el in self.content.subnodes_keys):\n                return None\n            elif len(as_filtered_list(self.content.subnodes_keys, lambda el: key.lower() in el.lower())) > 1:\n                logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n        else:\n            if key.lower() not in [el.lower() for el in self.content.subnodes_keys]:\n                return None\n            elif len(as_filtered_list(self.content.subnodes_keys, lambda el: el.lower() == key.lower())) > 1:\n                logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n\n        return self._rec_traverse(self, key, strict_matching)\n\n    def get_all_nodes_for_keys(\n        self,\n        keys: List[str],\n        strict_matching: bool = True,\n        stop_recurse_on_first_match: bool = False\n    ) -> List[BaseMarkdownNode]:\n\"\"\"\n        Return all nodes for the given keys, substring matching is supported.\n\n        Args:\n            keys: List of strings for the headers being collected\n            strict_matching: Force exact match of key with header vs. simple substring match\n            stop_recurse_on_first_match: Return first match of any of the keys and don't search subnodes\n\n        Returns: List of found markdown nodes\n        \"\"\"\n        if not strict_matching:\n            if not any(key in el for el in self.content.subnodes_keys for key in keys):\n                return []\n        elif not set(keys).intersection(self.content.subnodes_keys):\n            return []\n\n        return self._rec_traverse_all(self, keys, strict_matching, stop_recurse_on_first_match)\n\n    def get_all_headers_for_key(self, key: str, strict_matching: bool = True) -> Iterable[str]:\n\"\"\"Return all headers contained in the node with a given key.\"\"\"\n        if strict_matching:\n            return list(filter(lambda header: key == header, self.content.subnodes_keys)).__iter__()\n        else:\n            return list(filter(lambda header: key in header, self.content.subnodes_keys)).__iter__()\n\n    def get_node_header_lvl(self) -> Optional[int]:\n\"\"\"Return current node header level.\"\"\"\n        return self._get_header_level_if_valid(self.key)\n\n    def change_header_level_by(self, delta_level: int) -> None:\n\"\"\"\n        Change all headers in the tree by specified level up or down.\n\n        All children nodes will be modified by specified level as well.\n\n        Args:\n            delta_level: each header will be modified by this number, can be negative.\n        \"\"\"\n        # construct a map\n        header_map = {}\n        if self.key != 'root':\n            new_key = self._modify_header_level(self.key, delta_level)\n            header_map[self.key] = new_key\n        for key in self.content.subnodes_keys:\n            new_key = self._modify_header_level(key, delta_level)\n            header_map[key] = new_key\n\n        # go through all contents and modify headers\n        self._rec_traverse_header_update(self, header_map)\n\n    def delete_nodes_text(self, keys: List[str], strict_matching: bool = True) -> List[str]:\n\"\"\"Remove text from this node that is found in matching subnodes.\"\"\"\n        text_lines = self.content.raw_text.split('\\n')\n        matching_nodes = self.get_all_nodes_for_keys(keys, strict_matching, True)\n        # need to delete from end and proceed backwards\n        sorted_nodes = sorted(matching_nodes, key=lambda node: node.starting_line, reverse=True)\n        for node in sorted_nodes:\n            last_line = node.starting_line + len(node.content.raw_text.split('\\n'))\n            delete_list_from_list(text_lines, list(range(node.starting_line, last_line)))\n        return text_lines\n\n    @abstractmethod\n    def _build_tree(self, lines: List[str], root_key: str, starting_line: int,\n                    level: int) -> Tuple[BaseMarkdownNode, int]:\n\"\"\"Build a tree from the markdown recursively.\"\"\"\n        pass\n\n    def _modify_header_level(self, header: str, delta_level: int) -> str:\n\"\"\"Modify header level by specified level.\"\"\"\n        if delta_level == 0:\n            logger.debug('Nothing to modify in header, level 0 is given.')\n            return header\n\n        current_level = self._get_header_level_if_valid(header)\n        if current_level is None:\n            current_level = 0\n        if current_level + delta_level < 0:\n            logger.warning(\n                f'Cannot substract {delta_level} as level of {header} is {current_level}. All `#` will be removed.'\n            )\n            delta_level = current_level * -1\n\n        if current_level + delta_level == 0:\n            replacement = ''\n        else:\n            replacement = '#' * (current_level + delta_level)\n        header = header.replace('#' * current_level, replacement)\n\n        return header.strip(' ')\n\n    def _get_header_level_if_valid(self, line: str) -> Optional[int]:\n\"\"\"\n        Return a level of the header if the given line is indeed a header.\n\n        Level of the header is determined by the number of # symbols.\n        \"\"\"\n        header_symbols = re.match(md_const.HEADER_REGEX, line)\n        # Header is valid only if it line starts with header\n        if header_symbols is not None and header_symbols.regs[0][0] == 0:\n            return header_symbols.regs[0][1]\n        return None\n\n    def _does_start_with(self, line: str, start_chars: str) -> bool:\n\"\"\"Determine whether the line starts with given characters.\"\"\"\n        return line.startswith(start_chars)\n\n    def _does_contain(self, line: str, reg: str) -> bool:\n\"\"\"Determine if the line matches regex.\"\"\"\n        if len(line) == 0 and reg != r'':\n            return False\n        regexp = re.compile(reg)\n        return regexp.search(line) is not None\n\n    def _read_code_lines(self, lines: List[str], line: str, i: int) -> tuple[list[str], int]:\n\"\"\"Read code block.\"\"\"\n        code_lines = [line]\n        while True:\n            if i >= len(lines):\n                raise TrestleError(f'Code block is not closed: {code_lines}')\n\n            line = lines[i]\n            code_lines.append(line)\n            i += 1\n            if self._does_contain(line, md_const.CODEBLOCK_DEF):\n                break\n        return code_lines, i\n\n    def _read_html_block(self, lines: List[str], line: str, i: int, ending_regex: str) -> tuple[list[str], int]:\n\"\"\"Read html block.\"\"\"\n        html_block = [line]\n        if self._does_contain(line, r'<br[ /]*>'):\n            return html_block, i\n        if self._does_contain(line, ending_regex):\n            return html_block, i\n        while True:\n            if i >= len(lines):\n                raise TrestleError(f'HTML block is not closed: {html_block}')\n\n            line = lines[i]\n            html_block.append(line)\n            i += 1\n            if self._does_contain(line, ending_regex):\n                break\n        return html_block, i\n\n    def _read_table_block(self, lines: List[str], line: str, i: int) -> tuple[list[str], int]:\n\"\"\"Read table.\"\"\"\n        table_block = [line]\n        while True:\n            if i >= len(lines):\n                return table_block, i\n\n            line = lines[i]\n            if not self._does_contain(line, md_const.TABLE_REGEX):\n                table_block.append(line)\n                break\n            table_block.append(line)\n            i += 1\n        return table_block, i\n\n    def _rec_traverse(self, node: BaseMarkdownNode, key: str, strict_matching: bool) -> Optional[BaseMarkdownNode]:\n\"\"\"\n        Recursevely traverses the tree and searches for the given key.\n\n        If strict matching is turned off, node will be matched if key is a substring of the node's header.\n        \"\"\"\n        if key.lower() == node.key.lower() or (not strict_matching and key.lower() in node.key.lower()):\n            return node\n        if (not strict_matching and any(key.lower() in el.lower()\n                                        for el in node.content.subnodes_keys)) or (key.lower() in [\n                                            el.lower() for el in node.content.subnodes_keys\n                                        ]):\n            for subnode in node.subnodes:\n                matched_node = self._rec_traverse(subnode, key, strict_matching)\n                if matched_node is not None:\n                    return matched_node\n\n        return None\n\n    def _rec_traverse_all(\n        self, node: BaseMarkdownNode, keys: List[str], strict_matching: bool, stop_recurse_on_first_match: bool\n    ) -> List[BaseMarkdownNode]:\n\"\"\"\n        Recursevely traverse the tree and find all nodes matching the keys.\n\n        If strict matching is turned off, nodes will be matched if key is a substring of the node's header.\n        stop_recurse_on_first_match will return only the highest level key match and not any subnodes\n        \"\"\"\n        found_nodes: List[BaseMarkdownNode] = []\n        for key in keys:\n            if key == node.key or (not strict_matching and key in node.key):\n                found_nodes.append(node)\n                if stop_recurse_on_first_match:\n                    return found_nodes\n        for subnode in node.subnodes:\n            matched_nodes = self._rec_traverse_all(subnode, keys, strict_matching, stop_recurse_on_first_match)\n            found_nodes.extend(matched_nodes)\n        return found_nodes\n\n    def _rec_traverse_header_update(self, node: BaseMarkdownNode, header_map: Dict[str, str]) -> None:\n\"\"\"Recursively traverse tree and update the contents.\"\"\"\n        if node:\n            if node.key != 'root':\n                new_key = header_map[node.key]\n                node.key = new_key\n\n            # update text\n            lines = node.content.raw_text.split('\\n')\n            if lines:\n                for i in range(0, len(lines)):\n                    line = lines[i]\n                    if line in header_map.keys():\n                        new_key = header_map[line]\n                        lines[i] = new_key\n                    elif line.strip(' ') in header_map.keys():\n                        # keep spaces if any\n                        new_key = header_map[line.strip(' ')]\n                        lines[i] = line.replace(line.strip(' '), new_key)\n\n                node.content.raw_text = '\\n'.join(lines)\n\n            # update subnodes\n            if node.content.subnodes_keys:\n                for i in range(0, len(node.content.subnodes_keys)):\n                    subnode_key = node.content.subnodes_keys[i]\n                    if subnode_key in header_map.keys():\n                        new_key = header_map[subnode_key]\n                        node.content.subnodes_keys[i] = new_key\n\n        for subnode in node.subnodes:\n            self._rec_traverse_header_update(subnode, header_map)\n\n    def _get_max_header_lvl(self, lines: List[str]) -> int:\n\"\"\"Go through all lines to determine highest header level. Less # means higher.\"\"\"\n        min_lvl = math.inf\n        for line in lines:\n            line = line.strip(' ')\n            header_lvl = self._get_header_level_if_valid(line)\n\n            if header_lvl is not None and header_lvl < min_lvl:\n                min_lvl = header_lvl\n\n        return min_lvl - 1\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.__init__","title":"__init__(self, key, content, starting_line) special","text":"

                                                                            Initialize markdown node.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def __init__(self, key: str, content: BaseSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n    self.subnodes: List[BaseMarkdownNode] = []\n    self.key = key\n    self.content = content\n    self.starting_line = starting_line\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.build_tree_from_markdown","title":"build_tree_from_markdown(lines) classmethod","text":"

                                                                            Construct a tree out of the given markdown.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            @classmethod\ndef build_tree_from_markdown(cls, lines: List[str]) -> BaseMarkdownNode:\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n    ob = cls.__new__(cls)\n    start_level = ob._get_max_header_lvl(lines)\n    ob, _ = ob._build_tree(lines, 'root', 0, start_level)\n    return ob\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.change_header_level_by","title":"change_header_level_by(self, delta_level)","text":"

                                                                            Change all headers in the tree by specified level up or down.

                                                                            All children nodes will be modified by specified level as well.

                                                                            Parameters:

                                                                            Name Type Description Default delta_level int

                                                                            each header will be modified by this number, can be negative.

                                                                            required Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def change_header_level_by(self, delta_level: int) -> None:\n\"\"\"\n    Change all headers in the tree by specified level up or down.\n\n    All children nodes will be modified by specified level as well.\n\n    Args:\n        delta_level: each header will be modified by this number, can be negative.\n    \"\"\"\n    # construct a map\n    header_map = {}\n    if self.key != 'root':\n        new_key = self._modify_header_level(self.key, delta_level)\n        header_map[self.key] = new_key\n    for key in self.content.subnodes_keys:\n        new_key = self._modify_header_level(key, delta_level)\n        header_map[key] = new_key\n\n    # go through all contents and modify headers\n    self._rec_traverse_header_update(self, header_map)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.delete_nodes_text","title":"delete_nodes_text(self, keys, strict_matching=True)","text":"

                                                                            Remove text from this node that is found in matching subnodes.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def delete_nodes_text(self, keys: List[str], strict_matching: bool = True) -> List[str]:\n\"\"\"Remove text from this node that is found in matching subnodes.\"\"\"\n    text_lines = self.content.raw_text.split('\\n')\n    matching_nodes = self.get_all_nodes_for_keys(keys, strict_matching, True)\n    # need to delete from end and proceed backwards\n    sorted_nodes = sorted(matching_nodes, key=lambda node: node.starting_line, reverse=True)\n    for node in sorted_nodes:\n        last_line = node.starting_line + len(node.content.raw_text.split('\\n'))\n        delete_list_from_list(text_lines, list(range(node.starting_line, last_line)))\n    return text_lines\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_all_headers_for_key","title":"get_all_headers_for_key(self, key, strict_matching=True)","text":"

                                                                            Return all headers contained in the node with a given key.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def get_all_headers_for_key(self, key: str, strict_matching: bool = True) -> Iterable[str]:\n\"\"\"Return all headers contained in the node with a given key.\"\"\"\n    if strict_matching:\n        return list(filter(lambda header: key == header, self.content.subnodes_keys)).__iter__()\n    else:\n        return list(filter(lambda header: key in header, self.content.subnodes_keys)).__iter__()\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_all_headers_for_level","title":"get_all_headers_for_level(self, level)","text":"

                                                                            Return all headers per specified level of hierarchy.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def get_all_headers_for_level(self, level: int) -> Iterable[str]:\n\"\"\"Return all headers per specified level of hierarchy.\"\"\"\n    return list(\n        filter(lambda header: self._get_header_level_if_valid(header) == level, self.content.subnodes_keys)\n    ).__iter__()\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_all_nodes_for_keys","title":"get_all_nodes_for_keys(self, keys, strict_matching=True, stop_recurse_on_first_match=False)","text":"

                                                                            Return all nodes for the given keys, substring matching is supported.

                                                                            Parameters:

                                                                            Name Type Description Default keys List[str]

                                                                            List of strings for the headers being collected

                                                                            required strict_matching bool

                                                                            Force exact match of key with header vs. simple substring match

                                                                            True stop_recurse_on_first_match bool

                                                                            Return first match of any of the keys and don't search subnodes

                                                                            False

                                                                            Returns: List of found markdown nodes

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def get_all_nodes_for_keys(\n    self,\n    keys: List[str],\n    strict_matching: bool = True,\n    stop_recurse_on_first_match: bool = False\n) -> List[BaseMarkdownNode]:\n\"\"\"\n    Return all nodes for the given keys, substring matching is supported.\n\n    Args:\n        keys: List of strings for the headers being collected\n        strict_matching: Force exact match of key with header vs. simple substring match\n        stop_recurse_on_first_match: Return first match of any of the keys and don't search subnodes\n\n    Returns: List of found markdown nodes\n    \"\"\"\n    if not strict_matching:\n        if not any(key in el for el in self.content.subnodes_keys for key in keys):\n            return []\n    elif not set(keys).intersection(self.content.subnodes_keys):\n        return []\n\n    return self._rec_traverse_all(self, keys, strict_matching, stop_recurse_on_first_match)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_node_for_key","title":"get_node_for_key(self, key, strict_matching=True)","text":"

                                                                            Return a first node for the given key, substring matching is supported. The method is case insensitive.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def get_node_for_key(self, key: str, strict_matching: bool = True) -> Optional[BaseMarkdownNode]:\n\"\"\"Return a first node for the given key, substring matching is supported. The method is case insensitive.\"\"\"\n    if not strict_matching:\n        if not any(key.lower() in el.lower() for el in self.content.subnodes_keys):\n            return None\n        elif len(as_filtered_list(self.content.subnodes_keys, lambda el: key.lower() in el.lower())) > 1:\n            logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n    else:\n        if key.lower() not in [el.lower() for el in self.content.subnodes_keys]:\n            return None\n        elif len(as_filtered_list(self.content.subnodes_keys, lambda el: el.lower() == key.lower())) > 1:\n            logger.warning(f'Multiple nodes for {key} were found, only the first one will be returned.')\n\n    return self._rec_traverse(self, key, strict_matching)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseMarkdownNode.get_node_header_lvl","title":"get_node_header_lvl(self)","text":"

                                                                            Return current node header level.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def get_node_header_lvl(self) -> Optional[int]:\n\"\"\"Return current node header level.\"\"\"\n    return self._get_header_level_if_valid(self.key)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent","title":" BaseSectionContent ","text":"

                                                                            A content of the node.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            class BaseSectionContent:\n\"\"\"A content of the node.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize section content.\"\"\"\n        self.raw_text = ''\n        self.subnodes_keys: List[str] = []\n\n    def union(self, node: BaseMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n        self.subnodes_keys.append(node.key)\n        self.subnodes_keys.extend(node.content.subnodes_keys)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent.__init__","title":"__init__(self) special","text":"

                                                                            Initialize section content.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize section content.\"\"\"\n    self.raw_text = ''\n    self.subnodes_keys: List[str] = []\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.base_markdown_node/#trestle.core.markdown.base_markdown_node.BaseSectionContent.union","title":"union(self, node)","text":"

                                                                            Unites contents together.

                                                                            Source code in trestle/core/markdown/base_markdown_node.py
                                                                            def union(self, node: BaseMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n    self.subnodes_keys.append(node.key)\n    self.subnodes_keys.extend(node.content.subnodes_keys)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/","title":"control_markdown_node","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node","title":"trestle.core.markdown.control_markdown_node","text":"

                                                                            A control markdown node.

                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.tree_context","title":"tree_context","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode","title":" ControlMarkdownNode (BaseMarkdownNode) ","text":"

                                                                            Markdown will be read to the tree.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            class ControlMarkdownNode(BaseMarkdownNode):\n\"\"\"Markdown will be read to the tree.\"\"\"\n\n    def __init__(self, key: str, content: ControlSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n        super(ControlMarkdownNode, self).__init__(key, content, starting_line)\n        self.content: ControlSectionContent = content\n\n    def _build_tree(self,\n                    lines: List[str],\n                    root_key: str,\n                    starting_line: int,\n                    level: int,\n                    parent_part_id: str = '') -> Tuple[ControlMarkdownNode, int]:\n\"\"\"\n        Build a tree from the markdown recursively.\n\n        The tree is contructed with valid headers as node's keys\n        and node's content contains everything that is under that header.\n        The subsections are placed into node's children with the same structure.\n\n        A header is valid iff the line starts with # and it is not:\n          1. Inside of the html blocks\n          2. Inside single lined in the <> tags\n          3. Inside the html comment\n          4. Inside any table, code block or blockquotes\n\n        Specific Control Rules:\n          1. If we are in control statement or objective, no subsections are allowed.\n        \"\"\"\n        content = ControlSectionContent()\n        node_children = []\n        i = starting_line\n\n        section_heading_type = self._get_section_heading_type(root_key)\n\n        part_id, part_name, part_title, by_id_part = self._get_part_info_from_section_name(root_key, parent_part_id,\n                                                                                           section_heading_type)\n\n        current_key_lvl = self._get_header_level_if_valid(root_key)\n\n        if section_heading_type == ControlSectionType.UNDEFINED and tree_context.control_id:\n            logger.warning(\n                f'Undefined section {root_key} is found in the markdown for control {tree_context.control_id}. '\n                f'This section will be ignored. Please make sure the spelling is correct.'\n            )\n\n        if current_key_lvl and current_key_lvl == 1 and section_heading_type != ControlSectionType.EDITABLE_CONTENT:\n            # Parse control title\n            if tree_context.control_id:\n                logger.debug(\n                    f'Duplicate control_id is found for the markdown {root_key}, '\n                    f'make sure you have reset tree context before reading another markdown.'\n                    f'Use markdown processor to avoid this error.'\n                )\n                raise TrestleError(\n                    f'Multiple top-level headers are found but only one header is allowed. See line {root_key} '\n                    f'for control {tree_context.control_id}.'\n                )\n            tree_context.control_id, tree_context.control_group, tree_context.control_title = ControlMarkdownNode._parse_control_title_line(root_key)  # noqa: E501\n            content.control_id = tree_context.control_id\n            content.control_group = tree_context.control_group\n            content.control_title = tree_context.control_title\n\n        def _strip_prose_or_none(part: Optional[common.Part]):\n            if part and part.prose:\n                part.prose = part.prose.strip() if part.prose.strip() else None\n\n        def _add_child_prose_if_need(part: common.Part, text: str, should_add: bool):\n            if should_add:\n                part.prose += text\n\n        while i < len(lines):\n            line = lines[i].strip(' ')\n            header_lvl = self._get_header_level_if_valid(line)\n\n            if header_lvl is not None:\n                if header_lvl >= level + 1:\n                    if section_heading_type in [ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE]:\n                        raise TrestleError(\n                            f'Control Statement or Objective sections cannot contain subsections but found: {line}.'\n                            f'Please delete this subsection and refer to docs on the required format.'\n                        )\n                    # build subtree\n                    subtree, i = self._build_tree(lines, line, i + 1, level + 1, part_id)\n                    node_children.append(subtree)\n                    content.union(subtree)\n                    if content.part and subtree.content.part and section_heading_type not in [\n                            ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE, ControlSectionType.GUIDANCE\n                    ]:\n                        # Control statement, objective and guidance have special treatment\n                        # in those sections any subsections go to the prose rather than subparts.\n                        content.part.parts = as_list(content.part.parts)\n                        content.part.parts.append(subtree.content.part)\n                    # Control parts can have general markdown in the prose, if we are in the control part\n                    # add its contents under the prose of a parent\n                    _add_child_prose_if_need(\n                        content.part,\n                        subtree.content.raw_text,\n                        section_heading_type\n                        in [ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE, ControlSectionType.GUIDANCE]\n                    )\n                    continue\n                else:\n                    i -= 1  # need to revert back one line to properly handle next heading\n                    break  # level of the header is above or equal to the current level, subtree is over\n\n            if section_heading_type not in [ControlSectionType.UNDEFINED, ControlSectionType.EDITABLE_CONTENT]:\n                # Read part\n                content.part = self._create_part_if_needed(content.part, part_name, part_id)\n                content.part.title = part_title\n                read_parts = section_heading_type in [ControlSectionType.STATEMENT, ControlSectionType.OBJECTIVE]\n                if by_id_part and section_heading_type == ControlSectionType.EDITABLE_BY_ID_PART:\n                    content.by_id_name = by_id_part\n                i = self._process_part_line(i, line, lines, content.part, read_parts=read_parts)\n                continue\n\n            # Nothing to do, simply increment\n            i += 1\n\n        first_line_to_grab = starting_line - 1 if starting_line else 0\n        content.raw_text = '\\n'.join(lines[first_line_to_grab:i])\n\n        _strip_prose_or_none(content.part)\n\n        md_node = ControlMarkdownNode(key=root_key, content=content, starting_line=first_line_to_grab)\n        md_node.subnodes = node_children\n        return md_node, i\n\n    def get_control_statement(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control statement node.\"\"\"\n        return self.get_node_for_key('## Control Statement')\n\n    def get_control_objective(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control objective node.\"\"\"\n        return self.get_node_for_key(const.CONTROL_OBJECTIVE_HEADER)\n\n    def get_control_guidance(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control guidance node.\"\"\"\n        return self.get_node_for_key('## Control Guidance')\n\n    def get_by_id_parts(self) -> Dict[str, List[common.Part]]:\n\"\"\"Get by id editable parts.\"\"\"\n        part_id_to_parts_map = {}\n        for node_key in as_filtered_list(self.content.subnodes_keys, lambda k: re.match(const.PART_REGEX, k)):\n            # A by id part section\n            part_node = self.get_node_for_key(node_key)\n            if not part_node.content.part:\n                raise TrestleError(f'Error no part was found in section {part_node.key}.')\n            if part_node.content.by_id_name not in part_id_to_parts_map:\n                part_id_to_parts_map[part_node.content.by_id_name] = []\n            for subpart in part_node.subnodes:\n                # We only care about subsections of ## Part section\n                if subpart.content.part:\n                    part_id_to_parts_map[part_node.content.by_id_name].append(subpart.content.part)\n\n        return part_id_to_parts_map\n\n    def get_editable_parts_and_subparts(self) -> Optional[List[common.Part]]:\n\"\"\"Get editable parts and subparts if exist.\"\"\"\n        by_id_parts = self.get_by_id_parts()\n        exclude_parts_id = list(by_id_parts.keys())\n        editable_node = self.get_node_for_key(f'# {const.EDITABLE_CONTENT}')\n        parts = self._get_subparts(editable_node, exclude_parts_id)\n        return parts\n\n    def _get_subparts(self,\n                      control_node: ControlMarkdownNode,\n                      exclude_ids: List[str] = None) -> Optional[List[common.Part]]:\n\"\"\"Get subparts of the control part node if exists.\"\"\"\n        if not control_node:\n            raise TrestleError(\n                'No control node was provided to extract subparts. '\n                'Please make sure your markdown contains # Editable Content section.'\n            )\n        parts = []\n        for editable_part in as_filtered_list(control_node.subnodes, lambda p: p.content.part is not None):\n            if editable_part.content.part.id not in exclude_ids:\n                parts.append(editable_part.content.part)\n        return parts\n\n    def _get_section_heading_type(self, root_key: str) -> ControlSectionType:\n\"\"\"Determine the section type based on the heading.\"\"\"\n        if root_key.lower() == '## control statement':\n            return ControlSectionType.STATEMENT\n        elif root_key.lower() == '## control objective':\n            return ControlSectionType.OBJECTIVE\n        elif root_key.lower() == '## control guidance':\n            return ControlSectionType.GUIDANCE\n        elif self._does_contain(root_key, const.PART_REGEX):\n            return ControlSectionType.EDITABLE_BY_ID_PART\n        elif f'# {const.EDITABLE_CONTENT}'.lower() in root_key.lower():\n            return ControlSectionType.EDITABLE_CONTENT\n        elif self._does_contain(root_key, const.CONTROL_REGEX):\n            return ControlSectionType.GENERIC_CONTROL_PART\n        elif '### ' in root_key.lower():\n            return ControlSectionType.GENERIC_SUBPART\n\n        return ControlSectionType.UNDEFINED\n\n    def _get_part_info_from_section_name(self, root_key: str, parent_id: str,\n                                         section_heading_type: ControlSectionType) -> Tuple[str, str, str, str]:\n\"\"\"Get part information such as id, name and title based on the section heading.\"\"\"\n        part_id = ''\n        part_name = ''\n        part_title = None\n        by_part_id = None  # special case used for ## Part\n\n        if section_heading_type in [ControlSectionType.GUIDANCE, ControlSectionType.GENERIC_CONTROL_PART]:\n            prefix = const.CONTROL_HEADER + ' '\n            control_md_heading_label = root_key[len(prefix):].strip()\n            control_md_heading_label_ncname = ControlInterface.strip_to_make_ncname(control_md_heading_label)\n            control_md_heading_label_snakename = spaces_and_caps_to_snake(control_md_heading_label)\n\n        if section_heading_type == ControlSectionType.STATEMENT:\n            part_id = ControlInterface.create_statement_id(tree_context.control_id)\n            part_name = const.STATEMENT\n\n        if section_heading_type == ControlSectionType.OBJECTIVE:\n            part_id = f'{tree_context.control_id}_obj'\n            part_name = 'objective'\n\n        if section_heading_type == ControlSectionType.GUIDANCE:\n            # Read control guidance to a part object\n            part_id = ControlInterface.strip_to_make_ncname(tree_context.control_id + '_gdn')\n            part_name = control_md_heading_label_ncname\n\n        if section_heading_type == ControlSectionType.EDITABLE_BY_ID_PART:\n            # Read editable part\n            by_part_label = re.match(const.PART_REGEX, root_key.lower()).groups(0)[0]\n            control_label_map = tree_context.part_label_to_id_map.get(tree_context.control_id, None)\n            if control_label_map is None:\n                raise TrestleError(f'No label map found for control {tree_context.control_id}')\n            by_part_id = control_label_map.get(by_part_label, None)\n            if by_part_id is None:\n                raise TrestleError(f'No part id found for label {by_part_label} in control {tree_context.control_id}')\n\n            part_name = spaces_and_caps_to_snake(root_key.replace('#', '').replace('.', '').strip())\n            part_id = f'{by_part_id}'\n            part_title = root_key.replace('#', '').strip()\n\n        if section_heading_type == ControlSectionType.GENERIC_CONTROL_PART:\n            # Read other control parts to a part objects\n            part_name = control_md_heading_label_snakename\n            if tree_context.section_to_part_name_map:\n                if control_md_heading_label in tree_context.section_to_part_name_map:\n                    part_name = tree_context.section_to_part_name_map[control_md_heading_label]\n\n                part_id = f'{tree_context.control_id}_{part_name}'\n                part_title = control_md_heading_label\n            else:\n                part_id = spaces_and_caps_to_snake(tree_context.control_id + '_' + control_md_heading_label)\n\n        if section_heading_type == ControlSectionType.GENERIC_SUBPART:\n            # Read other control parts to a part objects\n            match = re.match(const.AFTER_HASHES_REGEX, root_key)\n            if not match:\n                raise TrestleError(f'Unexpected editable header {root_key} found in part {part_id}')\n            part_name_raw = match.groups(0)[0]\n            part_name = spaces_and_caps_to_snake(part_name_raw)\n            parent_suffix = parent_id + '.' if parent_id else ''\n            part_id = parent_suffix + part_name\n\n        return part_id, part_name, part_title, by_part_id\n\n    def get_other_control_parts(self) -> List[Optional[ControlMarkdownNode]]:\n\"\"\"Get all other control parts that are not statement, guidance or objective.\"\"\"\n        all_other_nodes = []\n        all_control_sections = self.get_all_headers_for_key(const.CONTROL_HEADER, False)\n        control_statement = self.get_control_statement()\n        control_objective = self.get_control_objective()\n        control_guidance = self.get_control_guidance()\n        control_statement_heading = control_statement.key if control_statement else ''\n        control_objective_heading = control_objective.key if control_objective else ''\n        control_guidance_heading = control_guidance.key if control_guidance else ''\n        for heading_key in all_control_sections:\n            if heading_key not in {control_statement_heading, control_objective_heading, control_guidance_heading}:\n                section_node = self.get_node_for_key(heading_key)\n                all_other_nodes.append(section_node)\n\n        return all_other_nodes\n\n    def _create_part_if_needed(self, content_part: common.Part, part_name: str, part_id: str, prose: str = ''):\n\"\"\"Create a new part if does not exist or return existing part.\"\"\"\n        if not content_part:\n            if not tree_context.control_id:\n                raise TrestleError(\n                    f'Unexpected error, control id, group and title should be before ## Control {part_name}.'\n                    'However, none was found.'\n                )\n\n            content_part = common.Part(name=part_name, id=part_id, prose=prose)\n\n        return content_part\n\n    def _process_part_line(\n        self, line_idx: int, line: str, lines: List[str], part: common.Part, read_parts: bool = True\n    ) -> int:\n\"\"\"\n        Process line for the part.\n\n        If the read_parts is given and the line starts with '-' then\n        the markdown list will be read to the subparts of the given part.\n        \"\"\"\n        if self._does_start_with(line, HTML_COMMENT_START):\n            comment_lines, line_idx = self._read_html_block(lines, line, line_idx + 1, HTML_COMMENT_END_REGEX)\n            if line_idx >= len(lines):\n                return line_idx\n            line = lines[line_idx]\n\n        if self._does_start_with(line, CODEBLOCK_DEF):\n            code_lines, line_idx = self._read_code_lines(lines, line, line_idx + 1)\n            if line_idx >= len(lines):\n                return line_idx\n            line = lines[line_idx]\n            part.prose += '\\n'.join(code_lines)\n\n        if not line or not line.lstrip():\n            # Empty line\n            part.prose += '\\n'\n            line_idx += 1\n            return line_idx\n\n        if line.lstrip()[0] != '-' or not read_parts:\n            # Line of text in prose\n            part.prose += line + '\\n'\n            line_idx += 1\n        else:\n            # A part of inside of statement part\n            if read_parts:\n                end_idx, parts = self._read_parts(0, line_idx, lines, part.id, [])\n                part.parts = none_if_empty(parts)\n                line_idx = end_idx\n            else:\n                logger.warning(\n                    f'{part.name} does not support subparts, ignoring {line} in control {tree_context.control_id}.'\n                )\n                line_idx += 1\n\n        return line_idx\n\n    def _read_parts(self, indent: int, ii: int, lines: List[str], parent_id: str,\n                    parts: List[common.Part]) -> Tuple[int, List[common.Part]]:\n\"\"\"If indentation level goes up or down, create new list or close current one.\"\"\"\n        while True:\n            ii, new_indent, line = ControlMarkdownNode._get_next_indent(ii, lines)\n            if new_indent < 0:\n                # we are done reading control statement\n                return ii, parts\n            if new_indent == indent:\n                # create new item part and add to current list of parts\n                id_text, prose = ControlMarkdownNode._read_part_id_prose(line)\n                # id_text is the part id and needs to be as a label property value\n                # if none is there then create one from previous part, or use default\n                if not id_text:\n                    prev_label = ControlInterface.get_label(parts[-1]) if parts else ''\n                    id_text = ControlMarkdownNode._create_next_label(prev_label, indent)\n                id_ = ControlInterface.strip_to_make_ncname(parent_id.rstrip('.') + '.' + id_text.strip('.'))\n                name = const.OBJECTIVE_PART if id_.find('_obj') > 0 else const.ITEM\n                prop = common.Property(name='label', value=id_text)\n                part = common.Part(name=name, id=id_, prose=prose, props=[prop])\n                if id_ in [p.id for p in parts]:\n                    logger.warning(\n                        f'Duplicate part id {id_} is found in markdown '\n                        f'{tree_context.control_id}. Please correct the part label in line {line}.'\n                    )\n                parts.append(part)\n                ii += 1\n            elif new_indent > indent:\n                # add new list of parts to last part and continue\n                if len(parts) == 0:\n                    raise TrestleError(f'Improper indentation structure: {line}')\n                ii, new_parts = self._read_parts(new_indent, ii, lines, parts[-1].id, [])\n                if new_parts:\n                    parts[-1].parts = new_parts\n            else:\n                # return list of sub-parts\n                return ii, parts\n\n    @staticmethod\n    def _indent(line: str) -> int:\n\"\"\"Measure indent of non-empty line.\"\"\"\n        if not line:\n            raise TrestleError('Empty line queried for indent.')\n        if line[0] not in [' ', '-', '\\t']:\n            return -1\n\n        indent = 0\n        for ii in range(len(line)):\n            if line[ii] == '-':\n                return indent\n            # if line is indented it must start with -\n            if line[ii] == '\\t':\n                # treat tab as two spaces\n                indent += 2\n            elif line[ii] != ' ':\n                break\n            else:\n                indent += 1\n        raise TrestleError(f'List elements must start with -: {line}')\n\n    @staticmethod\n    def _parse_control_title_line(line: str) -> Tuple[str, str, str]:\n\"\"\"Process the title line and extract the control id, group title (in brackets) and control title.\"\"\"\n        if line.count('-') == 0:\n            raise TrestleError(f'Markdown control title format error, missing - after control id: {line}')\n        split_line = line.split()\n        if len(split_line) < 3 or split_line[2] != '-':\n            raise TrestleError(f'Cannot parse control markdown title for control_id group and title: {line}')\n        # first token after the #\n        control_id = split_line[1]\n        group_title_start = line.find('\\[')\n        group_title_end = line.find('\\]')\n        if group_title_start < 0 or group_title_end < 0 or group_title_start > group_title_end:\n            raise TrestleError(f'unable to read group title for control {control_id}')\n        group_title = line[group_title_start + 2:group_title_end].strip()\n        control_title = line[group_title_end + 2:].strip()\n        return control_id, group_title, control_title\n\n    @staticmethod\n    def _read_part_id_prose(line: str) -> Tuple[str, str]:\n\"\"\"Extract the part id letter or number and prose from line.\"\"\"\n        start = line.find('\\\\[')\n        end = line.find('\\\\]')\n        prose = line.strip() if start < 0 else line[end + 2:].strip()\n        id_ = '' if start < 0 or end < 0 else line[start + 2:end]\n        return id_, prose\n\n    @staticmethod\n    def _create_next_label(prev_label: str, indent: int) -> str:\n\"\"\"\n        Create new label at indent level based on previous label if available.\n\n        If previous label is available, make this the next one in the sequence.\n        Otherwise start with a or 1 on alternate levels of indentation.\n        If alphabetic label reaches z, next one is aa.\n        Numeric ranges from 1 to 9, then 10 etc.\n        \"\"\"\n        if not prev_label:\n            # assume indent goes in steps of 2\n            return ['a', '1'][(indent // 2) % 2]\n        label_prefix = ''\n        label_suffix = prev_label\n        is_char = prev_label[-1] in string.ascii_letters\n        # if it isn't ending in letter or digit just append 'a' to end\n        if not is_char and prev_label[-1] not in string.digits:\n            return prev_label + 'a'\n        # break in middle of string if mixed types\n        if len(prev_label) > 1:\n            ii = len(prev_label) - 1\n            while ii >= 0:\n                if prev_label[ii] not in string.ascii_letters + string.digits:\n                    break\n                if (prev_label[ii] in string.ascii_letters) != is_char:\n                    break\n                ii -= 1\n            if ii >= 0:\n                label_prefix = prev_label[:(ii + 1)]\n                label_suffix = prev_label[(ii + 1):]\n\n        return label_prefix + ControlMarkdownNode._bump_label(label_suffix)\n\n    @staticmethod\n    def _bump_label(label: str) -> str:\n\"\"\"\n        Find next label given a string of 1 or more pure letters or digits.\n\n        The input must be either a string of digits or a string of ascii letters - or empty string.\n        \"\"\"\n        if not label:\n            return 'a'\n        if label[0] in string.digits:\n            return str(int(label) + 1)\n        if len(label) == 1 and label[0].lower() < 'z':\n            return chr(ord(label[0]) + 1)\n        # if this happens to be a string of letters, force it lowercase and bump\n        label = label.lower()\n        factor = 1\n        value = 0\n        # delta is needed because a counts as 0 when first value on right, but 1 for all others\n        delta = 0\n        for letter in label[::-1]:\n            value += (ord(letter) - ord('a') + delta) * factor\n            factor *= 26\n            delta = 1\n\n        value += 1\n\n        new_label = ''\n        delta = 0\n        while value > 0:\n            new_label += chr(ord('a') + value % 26 - delta)\n            value = value // 26\n            delta = 1\n        return new_label[::-1]\n\n    @staticmethod\n    def _get_next_indent(ii: int, lines: List[str], skip_empty_lines: bool = True) -> Tuple[int, int, str]:\n\"\"\"Seek to next content line.  ii remains at line read.\"\"\"\n        while 0 <= ii < len(lines):\n            line = lines[ii]\n            if line and not line.isspace():\n                if line[0] == '#':\n                    return ii, -1, line\n                indent = ControlMarkdownNode._indent(line)\n                if indent >= 0:\n                    # extract text after -\n                    start = indent + 1\n                    while start < len(line) and line[start] == ' ':\n                        start += 1\n                    if start >= len(line):\n                        raise TrestleError(f'Invalid line {line}')\n                    return ii, indent, line[start:]\n                return ii, indent, line\n            elif not skip_empty_lines:\n                return ii, -1, line\n            ii += 1\n        return ii, -1, ''\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.__init__","title":"__init__(self, key, content, starting_line) special","text":"Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def __init__(self, key: str, content: ControlSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n    super(ControlMarkdownNode, self).__init__(key, content, starting_line)\n    self.content: ControlSectionContent = content\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_by_id_parts","title":"get_by_id_parts(self)","text":"

                                                                            Get by id editable parts.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def get_by_id_parts(self) -> Dict[str, List[common.Part]]:\n\"\"\"Get by id editable parts.\"\"\"\n    part_id_to_parts_map = {}\n    for node_key in as_filtered_list(self.content.subnodes_keys, lambda k: re.match(const.PART_REGEX, k)):\n        # A by id part section\n        part_node = self.get_node_for_key(node_key)\n        if not part_node.content.part:\n            raise TrestleError(f'Error no part was found in section {part_node.key}.')\n        if part_node.content.by_id_name not in part_id_to_parts_map:\n            part_id_to_parts_map[part_node.content.by_id_name] = []\n        for subpart in part_node.subnodes:\n            # We only care about subsections of ## Part section\n            if subpart.content.part:\n                part_id_to_parts_map[part_node.content.by_id_name].append(subpart.content.part)\n\n    return part_id_to_parts_map\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_control_guidance","title":"get_control_guidance(self)","text":"

                                                                            Get control guidance node.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def get_control_guidance(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control guidance node.\"\"\"\n    return self.get_node_for_key('## Control Guidance')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_control_objective","title":"get_control_objective(self)","text":"

                                                                            Get control objective node.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def get_control_objective(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control objective node.\"\"\"\n    return self.get_node_for_key(const.CONTROL_OBJECTIVE_HEADER)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_control_statement","title":"get_control_statement(self)","text":"

                                                                            Get control statement node.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def get_control_statement(self) -> Optional[ControlMarkdownNode]:\n\"\"\"Get control statement node.\"\"\"\n    return self.get_node_for_key('## Control Statement')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_editable_parts_and_subparts","title":"get_editable_parts_and_subparts(self)","text":"

                                                                            Get editable parts and subparts if exist.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def get_editable_parts_and_subparts(self) -> Optional[List[common.Part]]:\n\"\"\"Get editable parts and subparts if exist.\"\"\"\n    by_id_parts = self.get_by_id_parts()\n    exclude_parts_id = list(by_id_parts.keys())\n    editable_node = self.get_node_for_key(f'# {const.EDITABLE_CONTENT}')\n    parts = self._get_subparts(editable_node, exclude_parts_id)\n    return parts\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlMarkdownNode.get_other_control_parts","title":"get_other_control_parts(self)","text":"

                                                                            Get all other control parts that are not statement, guidance or objective.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def get_other_control_parts(self) -> List[Optional[ControlMarkdownNode]]:\n\"\"\"Get all other control parts that are not statement, guidance or objective.\"\"\"\n    all_other_nodes = []\n    all_control_sections = self.get_all_headers_for_key(const.CONTROL_HEADER, False)\n    control_statement = self.get_control_statement()\n    control_objective = self.get_control_objective()\n    control_guidance = self.get_control_guidance()\n    control_statement_heading = control_statement.key if control_statement else ''\n    control_objective_heading = control_objective.key if control_objective else ''\n    control_guidance_heading = control_guidance.key if control_guidance else ''\n    for heading_key in all_control_sections:\n        if heading_key not in {control_statement_heading, control_objective_heading, control_guidance_heading}:\n            section_node = self.get_node_for_key(heading_key)\n            all_other_nodes.append(section_node)\n\n    return all_other_nodes\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent","title":" ControlSectionContent (BaseSectionContent) ","text":"

                                                                            A content of the node.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            class ControlSectionContent(BaseSectionContent):\n\"\"\"A content of the node.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize section content.\n\n        Attributes:\n            part: A part that is found in markdown. A part is defined in markdown by two or more # symbols\n            by_id_name: Required for parts defined as ## Part a in a markdown\n        \"\"\"\n        super(ControlSectionContent, self).__init__()\n        self.part = None\n        self.by_id_name = ''\n\n    def union(self, node: ControlMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n        super().union(node)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent.__init__","title":"__init__(self) special","text":"

                                                                            Initialize section content.

                                                                            Attributes:

                                                                            Name Type Description part

                                                                            A part that is found in markdown. A part is defined in markdown by two or more # symbols

                                                                            by_id_name

                                                                            Required for parts defined as ## Part a in a markdown

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def __init__(self):\n\"\"\"Initialize section content.\n\n    Attributes:\n        part: A part that is found in markdown. A part is defined in markdown by two or more # symbols\n        by_id_name: Required for parts defined as ## Part a in a markdown\n    \"\"\"\n    super(ControlSectionContent, self).__init__()\n    self.part = None\n    self.by_id_name = ''\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionContent.union","title":"union(self, node)","text":"

                                                                            Unites contents together.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def union(self, node: ControlMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n    super().union(node)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType","title":" ControlSectionType (Enum) ","text":"

                                                                            A type of the section in the markdown.

                                                                            Supported types: 1 - Control Statement 2 - Control Objective 3 - Control Guidance 4 - ## Part foo 5 - Control foo 6 - ### foo 7 - # Editable content

                                                                            Matching is case-insensitive.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            class ControlSectionType(Enum):\n\"\"\"A type of the section in the markdown.\n\n    Supported types:\n    1 - Control Statement\n    2 - Control Objective\n    3 - Control Guidance\n    4 - ## Part foo\n    5 - Control foo\n    6 - ### foo\n    7 - # Editable content\n\n    Matching is case-insensitive.\n    \"\"\"\n\n    STATEMENT = 1\n    OBJECTIVE = 2\n    GUIDANCE = 3\n    EDITABLE_BY_ID_PART = 4\n    GENERIC_CONTROL_PART = 5\n    GENERIC_SUBPART = 6\n    EDITABLE_CONTENT = 7\n    UNDEFINED = 8\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.EDITABLE_BY_ID_PART","title":"EDITABLE_BY_ID_PART","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.EDITABLE_CONTENT","title":"EDITABLE_CONTENT","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.GENERIC_CONTROL_PART","title":"GENERIC_CONTROL_PART","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.GENERIC_SUBPART","title":"GENERIC_SUBPART","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.GUIDANCE","title":"GUIDANCE","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.OBJECTIVE","title":"OBJECTIVE","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.STATEMENT","title":"STATEMENT","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.ControlSectionType.UNDEFINED","title":"UNDEFINED","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext","title":" TreeContext ","text":"

                                                                            A shared singleton tree context.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            class TreeContext:\n\"\"\"A shared singleton tree context.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize tree context.\"\"\"\n        self.control_id = ''\n        self.control_group = ''\n        self.control_title = ''\n        self.part_label_to_id_map = None\n        self.section_to_part_name_map = None\n\n    def reset(self):\n\"\"\"Reset global control tree context.\"\"\"\n        self.control_id = ''\n        self.control_group = ''\n        self.control_title = ''\n        self.part_label_to_id_map = None\n        self.section_to_part_name_map = None\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext.__init__","title":"__init__(self) special","text":"

                                                                            Initialize tree context.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def __init__(self):\n\"\"\"Initialize tree context.\"\"\"\n    self.control_id = ''\n    self.control_group = ''\n    self.control_title = ''\n    self.part_label_to_id_map = None\n    self.section_to_part_name_map = None\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.control_markdown_node/#trestle.core.markdown.control_markdown_node.TreeContext.reset","title":"reset(self)","text":"

                                                                            Reset global control tree context.

                                                                            Source code in trestle/core/markdown/control_markdown_node.py
                                                                            def reset(self):\n\"\"\"Reset global control tree context.\"\"\"\n    self.control_id = ''\n    self.control_group = ''\n    self.control_title = ''\n    self.part_label_to_id_map = None\n    self.section_to_part_name_map = None\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/","title":"docs_markdown_node","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node","title":"trestle.core.markdown.docs_markdown_node","text":"

                                                                            A docs markdown node.

                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode","title":" DocsMarkdownNode (BaseMarkdownNode) ","text":"

                                                                            Markdown will be read to the tree.

                                                                            Source code in trestle/core/markdown/docs_markdown_node.py
                                                                            class DocsMarkdownNode(BaseMarkdownNode):\n\"\"\"Markdown will be read to the tree.\"\"\"\n\n    def __init__(self, key: str, content: DocsSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n        super(DocsMarkdownNode, self).__init__(key, content, starting_line)\n        self.content: DocsSectionContent = content\n\n    @classmethod\n    def build_tree_from_markdown(cls, lines: List[str], governed_header: Optional[str] = None):\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n        ob = cls.__new__(cls)\n        start_level = ob._get_max_header_lvl(lines)\n        ob, _ = ob._build_tree(lines, 'root', 0, start_level, governed_header)\n        return ob\n\n    def _build_tree(\n        self,\n        lines: List[str],\n        root_key: str,\n        starting_line: int,\n        level: int,\n        governed_header: Optional[str] = None\n    ) -> Tuple[DocsMarkdownNode, int]:\n\"\"\"\n        Build a tree from the markdown recursively.\n\n        The tree is contructed with valid headers as node's keys\n        and node's content contains everything that is under that header.\n        The subsections are placed into node's children with the same structure.\n\n        A header is valid iff the line starts with # and it is not:\n          1. Inside of the html blocks\n          2. Inside single lined in the <> tags\n          3. Inside the html comment\n          4. Inside any table, code block or blockquotes\n        \"\"\"\n        content = DocsSectionContent()\n        node_children = []\n        i = starting_line\n\n        while True:\n            if i >= len(lines):\n                break\n            line = lines[i].strip(' ')\n            header_lvl = self._get_header_level_if_valid(line)\n\n            if header_lvl is not None:\n                if header_lvl >= level + 1:\n                    # build subtree\n                    subtree, i = self._build_tree(lines, line, i + 1, level + 1, governed_header)\n                    node_children.append(subtree)\n                    content.union(subtree)\n                else:\n                    break  # level of the header is above or equal to the current level, subtree is over\n            elif self._does_start_with(line, md_const.CODEBLOCK_DEF):\n                code_lines, i = self._read_code_lines(lines, line, i + 1)\n                content.code_lines.extend(code_lines)\n            elif self._does_start_with(line, md_const.HTML_COMMENT_START):\n                html_lines, i = self._read_html_block(lines, line, i + 1, md_const.HTML_COMMENT_END_REGEX)\n                content.html_lines.extend(html_lines)\n            elif self._does_contain(line, md_const.HTML_TAG_REGEX_START):\n                html_lines, i = self._read_html_block(lines, line, i + 1, md_const.HTML_TAG_REGEX_END)\n                content.html_lines.extend(html_lines)\n            elif self._does_start_with(line, md_const.TABLE_SYMBOL):\n                table_block, i = self._read_table_block(lines, line, i + 1)\n                content.tables.extend(table_block)\n            elif self._does_start_with(line, md_const.BLOCKQUOTE_CHAR):\n                content.blockquotes.append(line)\n                i += 1\n            elif governed_header is not None and self._does_contain(\n                    root_key, fr'^[#]+ {governed_header}$') and self._does_contain(line, md_const.GOVERNED_DOC_REGEX):\n                regexp = re.compile(md_const.GOVERNED_DOC_REGEX)\n                match = regexp.search(line)\n                header = match.group(0).strip('*').strip(':')\n                content.governed_document.append(header)\n                i += 1\n            else:\n                content.text.append(line)\n                i += 1\n\n        first_line_to_grab = starting_line - 1 if starting_line else 0\n        content.raw_text = '\\n'.join(lines[first_line_to_grab:i])\n        md_node = DocsMarkdownNode(key=root_key, content=content, starting_line=first_line_to_grab)\n        md_node.subnodes = node_children\n        return md_node, i\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode.__init__","title":"__init__(self, key, content, starting_line) special","text":"Source code in trestle/core/markdown/docs_markdown_node.py
                                                                            def __init__(self, key: str, content: DocsSectionContent, starting_line: int):\n\"\"\"Initialize markdown node.\"\"\"\n    super(DocsMarkdownNode, self).__init__(key, content, starting_line)\n    self.content: DocsSectionContent = content\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsMarkdownNode.build_tree_from_markdown","title":"build_tree_from_markdown(lines, governed_header=None) classmethod","text":"

                                                                            Construct a tree out of the given markdown.

                                                                            Source code in trestle/core/markdown/docs_markdown_node.py
                                                                            @classmethod\ndef build_tree_from_markdown(cls, lines: List[str], governed_header: Optional[str] = None):\n\"\"\"Construct a tree out of the given markdown.\"\"\"\n    ob = cls.__new__(cls)\n    start_level = ob._get_max_header_lvl(lines)\n    ob, _ = ob._build_tree(lines, 'root', 0, start_level, governed_header)\n    return ob\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent","title":" DocsSectionContent (BaseSectionContent) ","text":"

                                                                            A content of the node.

                                                                            Source code in trestle/core/markdown/docs_markdown_node.py
                                                                            class DocsSectionContent(BaseSectionContent):\n\"\"\"A content of the node.\"\"\"\n\n    def __init__(self):\n\"\"\"Initialize section content.\"\"\"\n        super(DocsSectionContent, self).__init__()\n        self.tables = []\n        self.text = []\n        self.code_lines = []\n        self.html_lines = []\n        self.blockquotes = []\n        self.governed_document = []\n\n    def union(self, node: DocsMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n        super().union(node)\n        self.code_lines.extend(node.content.code_lines)\n        self.html_lines.extend(node.content.html_lines)\n        self.tables.extend(node.content.tables)\n        self.blockquotes.extend(node.content.blockquotes)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent.__init__","title":"__init__(self) special","text":"Source code in trestle/core/markdown/docs_markdown_node.py
                                                                            def __init__(self):\n\"\"\"Initialize section content.\"\"\"\n    super(DocsSectionContent, self).__init__()\n    self.tables = []\n    self.text = []\n    self.code_lines = []\n    self.html_lines = []\n    self.blockquotes = []\n    self.governed_document = []\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.docs_markdown_node/#trestle.core.markdown.docs_markdown_node.DocsSectionContent.union","title":"union(self, node)","text":"

                                                                            Unites contents together.

                                                                            Source code in trestle/core/markdown/docs_markdown_node.py
                                                                            def union(self, node: DocsMarkdownNode) -> None:\n\"\"\"Unites contents together.\"\"\"\n    super().union(node)\n    self.code_lines.extend(node.content.code_lines)\n    self.html_lines.extend(node.content.html_lines)\n    self.tables.extend(node.content.tables)\n    self.blockquotes.extend(node.content.blockquotes)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_api/","title":"markdown_api","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api","title":"trestle.core.markdown.markdown_api","text":"

                                                                            A markdown API.

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI","title":" MarkdownAPI ","text":"

                                                                            A common API that wraps around the existing markdown functionality.

                                                                            Source code in trestle/core/markdown/markdown_api.py
                                                                            class MarkdownAPI:\n\"\"\"A common API that wraps around the existing markdown functionality.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize markdown API.\"\"\"\n        self.processor = MarkdownProcessor()\n        self.validator = None\n\n    def load_validator_with_template(\n        self,\n        md_template_path: pathlib.Path,\n        validate_yaml_header: bool,\n        validate_md_body: bool,\n        governed_section: Optional[str] = None,\n        validate_template: bool = False\n    ) -> None:\n\"\"\"Load and initialize markdown validator.\"\"\"\n        try:\n            self.processor.governed_header = governed_section\n            if validate_template:\n                template_header, template_tree = self.processor.process_markdown(md_template_path, validate_yaml_header,\n                                                                                 validate_md_body or governed_section is\n                                                                                 not None)\n            else:\n                template_header, template_tree = self.processor.process_markdown(md_template_path)\n\n            if not template_header and validate_yaml_header:\n                raise TrestleError(f'Expected yaml header for markdown template where none exists {md_template_path}')\n\n            self.validator = MarkdownValidator(\n                md_template_path,\n                template_header,\n                template_tree,\n                validate_yaml_header,\n                validate_md_body,\n                governed_section\n            )\n        except TrestleError as e:\n            raise TrestleError(f'Error while loading markdown template {md_template_path}: {e}.')\n\n    def validate_instance(self, md_instance_path: pathlib.Path) -> bool:\n\"\"\"Validate a given markdown instance against a template.\"\"\"\n        if self.validator is None:\n            raise TrestleError('Markdown validator is not initialized, load template first.')\n        instance_header, instance_tree = self.processor.process_markdown(md_instance_path)\n        return self.validator.is_valid_against_template(md_instance_path, instance_header, instance_tree)\n\n    def write_markdown_with_header(self, path: pathlib.Path, header: Dict[str, str], md_body: str) -> None:\n\"\"\"Write markdown with the YAML header.\"\"\"\n        try:\n            # use encoding to handle character sets as well as possible\n            with open(path, 'w', encoding=const.FILE_ENCODING, errors='replace') as md_file:\n                md_file.write('---\\n')\n                yaml.safe_dump(header, md_file, sort_keys=False)\n                md_file.write('---\\n\\n')\n                md_file.write(md_body)\n        except IOError as e:\n            raise TrestleError(f'Error while writing markdown file: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.__init__","title":"__init__(self) special","text":"

                                                                            Initialize markdown API.

                                                                            Source code in trestle/core/markdown/markdown_api.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize markdown API.\"\"\"\n    self.processor = MarkdownProcessor()\n    self.validator = None\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.load_validator_with_template","title":"load_validator_with_template(self, md_template_path, validate_yaml_header, validate_md_body, governed_section=None, validate_template=False)","text":"

                                                                            Load and initialize markdown validator.

                                                                            Source code in trestle/core/markdown/markdown_api.py
                                                                            def load_validator_with_template(\n    self,\n    md_template_path: pathlib.Path,\n    validate_yaml_header: bool,\n    validate_md_body: bool,\n    governed_section: Optional[str] = None,\n    validate_template: bool = False\n) -> None:\n\"\"\"Load and initialize markdown validator.\"\"\"\n    try:\n        self.processor.governed_header = governed_section\n        if validate_template:\n            template_header, template_tree = self.processor.process_markdown(md_template_path, validate_yaml_header,\n                                                                             validate_md_body or governed_section is\n                                                                             not None)\n        else:\n            template_header, template_tree = self.processor.process_markdown(md_template_path)\n\n        if not template_header and validate_yaml_header:\n            raise TrestleError(f'Expected yaml header for markdown template where none exists {md_template_path}')\n\n        self.validator = MarkdownValidator(\n            md_template_path,\n            template_header,\n            template_tree,\n            validate_yaml_header,\n            validate_md_body,\n            governed_section\n        )\n    except TrestleError as e:\n        raise TrestleError(f'Error while loading markdown template {md_template_path}: {e}.')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.validate_instance","title":"validate_instance(self, md_instance_path)","text":"

                                                                            Validate a given markdown instance against a template.

                                                                            Source code in trestle/core/markdown/markdown_api.py
                                                                            def validate_instance(self, md_instance_path: pathlib.Path) -> bool:\n\"\"\"Validate a given markdown instance against a template.\"\"\"\n    if self.validator is None:\n        raise TrestleError('Markdown validator is not initialized, load template first.')\n    instance_header, instance_tree = self.processor.process_markdown(md_instance_path)\n    return self.validator.is_valid_against_template(md_instance_path, instance_header, instance_tree)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_api/#trestle.core.markdown.markdown_api.MarkdownAPI.write_markdown_with_header","title":"write_markdown_with_header(self, path, header, md_body)","text":"

                                                                            Write markdown with the YAML header.

                                                                            Source code in trestle/core/markdown/markdown_api.py
                                                                            def write_markdown_with_header(self, path: pathlib.Path, header: Dict[str, str], md_body: str) -> None:\n\"\"\"Write markdown with the YAML header.\"\"\"\n    try:\n        # use encoding to handle character sets as well as possible\n        with open(path, 'w', encoding=const.FILE_ENCODING, errors='replace') as md_file:\n            md_file.write('---\\n')\n            yaml.safe_dump(header, md_file, sort_keys=False)\n            md_file.write('---\\n\\n')\n            md_file.write(md_body)\n    except IOError as e:\n        raise TrestleError(f'Error while writing markdown file: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_const/","title":"markdown_const","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const","title":"trestle.core.markdown.markdown_const","text":"

                                                                            Markdown specific constants.

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.BLOCKQUOTE_CHAR","title":"BLOCKQUOTE_CHAR","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.CODEBLOCK_DEF","title":"CODEBLOCK_DEF","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.GOVERNED_DOC_REGEX","title":"GOVERNED_DOC_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HEADER_REGEX","title":"HEADER_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_COMMENT_END_REGEX","title":"HTML_COMMENT_END_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_COMMENT_START","title":"HTML_COMMENT_START","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_TAG_REGEX_END","title":"HTML_TAG_REGEX_END","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.HTML_TAG_REGEX_START","title":"HTML_TAG_REGEX_START","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.INLINE_CODE_CHAR","title":"INLINE_CODE_CHAR","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.JINJA_DATESTAMP_FORMAT","title":"JINJA_DATESTAMP_FORMAT","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.LIST_CHAR","title":"LIST_CHAR","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.SUBSTITUTION_REGEX","title":"SUBSTITUTION_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.TABLE_REGEX","title":"TABLE_REGEX","text":""},{"location":"api_reference/trestle.core.markdown.markdown_const/#trestle.core.markdown.markdown_const.TABLE_SYMBOL","title":"TABLE_SYMBOL","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/","title":"markdown_processor","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor","title":"trestle.core.markdown.markdown_processor","text":"

                                                                            A markdown processor.

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor","title":" MarkdownProcessor ","text":"

                                                                            A markdown processor.

                                                                            Source code in trestle/core/markdown/markdown_processor.py
                                                                            class MarkdownProcessor:\n\"\"\"A markdown processor.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize markdown processor.\"\"\"\n        self.governed_header = None\n\n    def render_gfm_to_html(self, markdown_text: str) -> str:\n\"\"\"Render given Github Flavored Markdown to HTML.\"\"\"\n        try:\n            html = cmarkgfm.github_flavored_markdown_to_html(markdown_text)\n            return html\n        except ValueError as e:\n            raise TrestleError(f'Not a valid Github Flavored markdown: {e}.')\n\n    def process_markdown(self,\n                         md_path: pathlib.Path,\n                         read_header: bool = True,\n                         read_body: bool = True) -> Tuple[Dict, DocsMarkdownNode]:\n\"\"\"Parse the markdown and builds the tree to operate over it.\"\"\"\n        header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header, read_body)\n\n        _ = self.render_gfm_to_html(markdown_wo_header)\n\n        lines = markdown_wo_header.split('\\n')\n        tree = DocsMarkdownNode.build_tree_from_markdown(lines, self.governed_header)\n        return header, tree\n\n    def process_control_markdown(\n        self,\n        md_path: pathlib.Path,\n        cli_section_dict: Dict[str, str] = None,\n        part_label_to_id_map: Dict[str, str] = None\n    ) -> Tuple[Dict, ControlMarkdownNode]:\n\"\"\"Parse control markdown and build tree with identified OSCAL components.\"\"\"\n        try:\n            header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header=True, read_body=True)\n\n            section_to_part_name_map = {}\n            if cli_section_dict is not None:\n                # Read x-trestle-sections to the dictionary and merge it with CLI provided dictionary\n                yaml_header_sections_dict = header.get(const.SECTIONS_TAG, {})\n                merged_dict = merge_dicts(yaml_header_sections_dict, cli_section_dict)\n                section_to_part_name_map = {v: k for k, v in merged_dict.items()}\n            _ = self.render_gfm_to_html(markdown_wo_header)\n\n            lines = markdown_wo_header.split('\\n')\n            tree_context.reset()\n            tree_context.section_to_part_name_map = section_to_part_name_map\n            tree_context.part_label_to_id_map = part_label_to_id_map\n            tree = ControlMarkdownNode.build_tree_from_markdown(lines)\n            tree_context.reset()\n            return header, tree\n        except TrestleError as e:\n            logger.error(f'Error while reading control markdown: {md_path}: {e}')\n            raise e\n\n    def read_markdown_wo_processing(self,\n                                    md_path: pathlib.Path,\n                                    read_header: bool = True,\n                                    read_body: bool = True) -> Tuple[Dict, str]:\n\"\"\"Read markdown header to dictionary and body to string.\"\"\"\n        try:\n            contents = frontmatter.loads(md_path.open('r', encoding=const.FILE_ENCODING).read())\n            header = {}\n            markdown_wo_header = ''\n            if read_header:\n                header = contents.metadata\n            if read_body:\n                markdown_wo_header = contents.content\n\n            return header, markdown_wo_header\n        except UnicodeDecodeError as e:\n            logger.debug(traceback.format_exc())\n            raise TrestleError(f'Markdown cannot be decoded into {const.FILE_ENCODING}, error: {e}')\n        except ScannerError as e:\n            logger.debug(traceback.format_exc())\n            raise TrestleError(f'Header is not in a valid YAML format: {e}')\n        except FileNotFoundError as e:\n            logger.debug(traceback.format_exc())\n            raise TrestleError(f'Markdown with path {md_path}, not found: {e}')\n\n    def fetch_value_from_header(self, md_path: pathlib.Path, key: str) -> Optional[str]:\n\"\"\"Fetch value for the given key from the markdown header if exists.\"\"\"\n        header, _ = self.read_markdown_wo_processing(md_path)\n        value = None\n\n        if key in header.keys():\n            value = header[key]\n\n        return value\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.__init__","title":"__init__(self) special","text":"

                                                                            Initialize markdown processor.

                                                                            Source code in trestle/core/markdown/markdown_processor.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize markdown processor.\"\"\"\n    self.governed_header = None\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.fetch_value_from_header","title":"fetch_value_from_header(self, md_path, key)","text":"

                                                                            Fetch value for the given key from the markdown header if exists.

                                                                            Source code in trestle/core/markdown/markdown_processor.py
                                                                            def fetch_value_from_header(self, md_path: pathlib.Path, key: str) -> Optional[str]:\n\"\"\"Fetch value for the given key from the markdown header if exists.\"\"\"\n    header, _ = self.read_markdown_wo_processing(md_path)\n    value = None\n\n    if key in header.keys():\n        value = header[key]\n\n    return value\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.process_control_markdown","title":"process_control_markdown(self, md_path, cli_section_dict=None, part_label_to_id_map=None)","text":"

                                                                            Parse control markdown and build tree with identified OSCAL components.

                                                                            Source code in trestle/core/markdown/markdown_processor.py
                                                                            def process_control_markdown(\n    self,\n    md_path: pathlib.Path,\n    cli_section_dict: Dict[str, str] = None,\n    part_label_to_id_map: Dict[str, str] = None\n) -> Tuple[Dict, ControlMarkdownNode]:\n\"\"\"Parse control markdown and build tree with identified OSCAL components.\"\"\"\n    try:\n        header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header=True, read_body=True)\n\n        section_to_part_name_map = {}\n        if cli_section_dict is not None:\n            # Read x-trestle-sections to the dictionary and merge it with CLI provided dictionary\n            yaml_header_sections_dict = header.get(const.SECTIONS_TAG, {})\n            merged_dict = merge_dicts(yaml_header_sections_dict, cli_section_dict)\n            section_to_part_name_map = {v: k for k, v in merged_dict.items()}\n        _ = self.render_gfm_to_html(markdown_wo_header)\n\n        lines = markdown_wo_header.split('\\n')\n        tree_context.reset()\n        tree_context.section_to_part_name_map = section_to_part_name_map\n        tree_context.part_label_to_id_map = part_label_to_id_map\n        tree = ControlMarkdownNode.build_tree_from_markdown(lines)\n        tree_context.reset()\n        return header, tree\n    except TrestleError as e:\n        logger.error(f'Error while reading control markdown: {md_path}: {e}')\n        raise e\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.process_markdown","title":"process_markdown(self, md_path, read_header=True, read_body=True)","text":"

                                                                            Parse the markdown and builds the tree to operate over it.

                                                                            Source code in trestle/core/markdown/markdown_processor.py
                                                                            def process_markdown(self,\n                     md_path: pathlib.Path,\n                     read_header: bool = True,\n                     read_body: bool = True) -> Tuple[Dict, DocsMarkdownNode]:\n\"\"\"Parse the markdown and builds the tree to operate over it.\"\"\"\n    header, markdown_wo_header = self.read_markdown_wo_processing(md_path, read_header, read_body)\n\n    _ = self.render_gfm_to_html(markdown_wo_header)\n\n    lines = markdown_wo_header.split('\\n')\n    tree = DocsMarkdownNode.build_tree_from_markdown(lines, self.governed_header)\n    return header, tree\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.read_markdown_wo_processing","title":"read_markdown_wo_processing(self, md_path, read_header=True, read_body=True)","text":"

                                                                            Read markdown header to dictionary and body to string.

                                                                            Source code in trestle/core/markdown/markdown_processor.py
                                                                            def read_markdown_wo_processing(self,\n                                md_path: pathlib.Path,\n                                read_header: bool = True,\n                                read_body: bool = True) -> Tuple[Dict, str]:\n\"\"\"Read markdown header to dictionary and body to string.\"\"\"\n    try:\n        contents = frontmatter.loads(md_path.open('r', encoding=const.FILE_ENCODING).read())\n        header = {}\n        markdown_wo_header = ''\n        if read_header:\n            header = contents.metadata\n        if read_body:\n            markdown_wo_header = contents.content\n\n        return header, markdown_wo_header\n    except UnicodeDecodeError as e:\n        logger.debug(traceback.format_exc())\n        raise TrestleError(f'Markdown cannot be decoded into {const.FILE_ENCODING}, error: {e}')\n    except ScannerError as e:\n        logger.debug(traceback.format_exc())\n        raise TrestleError(f'Header is not in a valid YAML format: {e}')\n    except FileNotFoundError as e:\n        logger.debug(traceback.format_exc())\n        raise TrestleError(f'Markdown with path {md_path}, not found: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_processor/#trestle.core.markdown.markdown_processor.MarkdownProcessor.render_gfm_to_html","title":"render_gfm_to_html(self, markdown_text)","text":"

                                                                            Render given Github Flavored Markdown to HTML.

                                                                            Source code in trestle/core/markdown/markdown_processor.py
                                                                            def render_gfm_to_html(self, markdown_text: str) -> str:\n\"\"\"Render given Github Flavored Markdown to HTML.\"\"\"\n    try:\n        html = cmarkgfm.github_flavored_markdown_to_html(markdown_text)\n        return html\n    except ValueError as e:\n        raise TrestleError(f'Not a valid Github Flavored markdown: {e}.')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_validator/","title":"markdown_validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator","title":"trestle.core.markdown.markdown_validator","text":"

                                                                            Markdown Validator.

                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator","title":" MarkdownValidator ","text":"

                                                                            A markdown validator. Validates markdown instance against given template.

                                                                            Source code in trestle/core/markdown/markdown_validator.py
                                                                            class MarkdownValidator:\n\"\"\"A markdown validator. Validates markdown instance against given template.\"\"\"\n\n    def __init__(\n        self,\n        tmp_path: pathlib.Path,\n        template_header: Dict,\n        template_tree: DocsMarkdownNode,\n        validate_yaml_header: bool,\n        validate_md_body: bool,\n        governed_section: Optional[str] = None\n    ):\n\"\"\"Initialize markdown validator.\"\"\"\n        self._validate_yaml_header = validate_yaml_header\n        self._validate_md_body = validate_md_body\n        self.governed_section = governed_section.strip(' ') if governed_section is not None else None\n        self.template_header = template_header\n        self.template_tree = template_tree\n        self.template_path = tmp_path\n        self.template_version = self.extract_template_version(self.template_header)\n\n        if self.template_version not in str(self.template_path):\n            raise TrestleError(\n                f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n                + f'Move the template to the folder {self.template_version}'\n            )\n        if 'Version' in self.template_header.keys() and self.template_header['Version'] != self.template_version:\n            raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n        self._ignore_headers = []\n        for key in self.template_header.keys():\n            if key.lower().startswith('x-trestle-'):\n                self._ignore_headers.append(key.lower())\n                if key.lower() == 'x-trestle-ignore':\n                    for key2 in template_header['x-trestle-ignore']:\n                        self._ignore_headers.append(key2.lower())\n\n    def is_valid_against_template(\n        self, instance: pathlib.Path, instance_header: Dict, instance_tree: DocsMarkdownNode\n    ) -> bool:\n\"\"\"\n        Validate instance markdown against template.\n\n        Instance is correct against a template iff:\n            1. For YAML header keys:\n                a. All keys from the template are present and not modified\n                b. Template version in the template and instance match\n            2. On the Markdown w/o YAML header:\n                a. No additional headers of the level 1 were added\n                b. Headers were not reordered\n                c. Headers in the instance should be a superset of the template headers\n                d. Headers must be in heirarchical order (i.e. # then ### then ## is not allowed)\n            3. If Governed Header is given then:\n                a. Governed Header is not modified\n                b. All keys (i.e. key: something) inside the section are present\n\n        Args:\n            instance: a path to the markdown instance that should be validated\n            instance_header: a YAML header extracted from the markdown\n            instance_tree: a tree structure representing markdown contents\n        Returns:\n            Whether or not the the candidate is valid against the template.\n        \"\"\"\n        if self._validate_yaml_header:\n            headers_match = self.compare_keys(self.template_header, instance_header, self._ignore_headers)\n\n            if not headers_match:\n                logger.info(f'YAML header mismatch between template {self.template_path} and instance {instance}')\n                return False\n            elif headers_match and not self._validate_md_body:\n                return True\n\n        if self.governed_section is not None:\n            instance_gov_nodes = instance_tree.get_all_nodes_for_keys([self.governed_section], False)\n            template_gov_nodes = self.template_tree.get_all_nodes_for_keys([self.governed_section], False)\n\n            if not instance_gov_nodes:\n                logger.info(f'Governed section {self.governed_section} not found in instance: {instance}')\n                return False\n\n            if not template_gov_nodes:\n                logger.info(f'Governed section {self.governed_section} not found in template: {self.template_path}')\n                return False\n\n            if [node.key for node in instance_gov_nodes] != [node.key for node in template_gov_nodes]:\n                logger.info(\n                    f'Governed sections were changed, '\n                    f'template expects: {[node.key for node in template_gov_nodes]},'\n                    f'but found {[node.key for node in instance_gov_nodes]}.'\n                )\n                return False\n\n            for instance_gov_node, template_gov_node in zip(instance_gov_nodes, template_gov_nodes):\n                instance_keys = instance_gov_node.content.governed_document\n                template_keys = template_gov_node.content.governed_document\n\n                is_valid = self._validate_headings(instance, template_keys, instance_keys)\n                if not is_valid:\n                    return False\n\n        if self._validate_md_body:\n            instance_keys = instance_tree.content.subnodes_keys\n            template_keys = self.template_tree.content.subnodes_keys\n            if len(template_keys) > len(instance_keys):\n                logger.info(f'Headings in the instance: {instance} were removed.')\n                return False\n\n            instance_lvl1_keys = list(instance_tree.get_all_headers_for_level(1))\n            template_lvl1_keys = list(self.template_tree.get_all_headers_for_level(1))\n            if len(template_lvl1_keys) < len(instance_lvl1_keys):\n                logger.info(f'New headers of level 1 were added to the markdown instance: {instance}. ')\n                return False\n\n            is_valid = self._validate_headings(instance, template_keys, instance_keys)\n            if not is_valid:\n                return False\n\n        return True\n\n    @classmethod\n    def compare_keys(\n        cls,\n        template: Dict[str, Any],\n        candidate: Dict[str, Any],\n        ignore_fields: Optional[Dict[str, Any]] = None\n    ) -> bool:\n\"\"\"\n        Compare a template dictionary against a candidate as to whether key structure is maintained.\n\n        Args:\n            template: Template dict which is used as a model of key-value pairs\n            candidate: Candidate dictionary to be measured\n        Returns:\n            Whether or not the the candidate matches the template keys.\n        \"\"\"\n        if ignore_fields is None:\n            ignore_fields = []\n        for key in list(candidate.keys()):\n            if key.lower() in ignore_fields:\n                candidate.pop(key)\n        for key in list(template.keys()):\n            if key.lower() in ignore_fields:\n                template.pop(key)\n        template_version = cls.extract_template_version(template)\n        candidate_version = cls.extract_template_version(candidate)\n        if template_version != candidate_version:\n            logger.info(f'Versions of the template {template_version} and instance {candidate_version} are different')\n            return False\n\n        if len(template.keys()) != len(candidate.keys()):\n            logger.info(f'Number of keys does not match in template {template} and instance {candidate}')\n            return False\n        for key in template.keys():\n            if key in candidate.keys():\n                if type(template[key]) == dict:\n                    if type(candidate[key]) == dict:\n                        status = cls.compare_keys(template[key], candidate[key], ignore_fields)\n                        if not status:\n                            return status\n                    else:\n                        logger.info(f'Value under {key} must be dictionary in candidate {candidate}')\n                        return False\n            else:\n                logger.info(f'Key {key} is not in candidate {candidate}')\n                return False\n        return True\n\n    def _validate_headings(self, instance: pathlib.Path, template_keys: List[str], instance_keys: List[str]) -> bool:\n\"\"\"Validate instance headings against template.\"\"\"\n        if len(template_keys) > len(instance_keys):\n            logger.info(\n                f'Headings in the instance: {instance} were removed.'\n                f'Expected {len(template_keys)} headings, but found only {len(instance_keys)}.'\n            )\n            return False\n        template_header_pointer = 0\n        present_keys = []\n        for key in instance_keys:\n            if template_header_pointer >= len(template_keys):\n                break\n            if key in template_keys and key not in present_keys:\n                present_keys.append(template_keys[template_keys.index(key)])\n                template_header_pointer += 1\n            elif re.search(md_const.SUBSTITUTION_REGEX, template_keys[template_header_pointer]) is not None:\n                present_keys.append(template_keys[template_header_pointer])\n                template_header_pointer += 1  # skip headers with substitutions\n        diff_keys = set(template_keys) - set(present_keys)\n        if template_header_pointer != len(template_keys) and len(diff_keys) > 0:\n            logger.info(\n                f'Headings in the instance: {instance} were removed. '\n                f'Expected {len(template_keys)} headings, but found only {template_header_pointer}.'\n            )\n            for result in as_list(diff_keys):\n                logger.info(f'Heading {result} in the instance: {instance} was removed or not present ')\n            return False\n        return True\n\n    @classmethod\n    def extract_template_version(cls, header: Dict[str, Any]) -> Optional[str]:\n\"\"\"\n        Extract the template version from the header.\n\n        If no header is found then starting version(0.0.1) will be used by default\n        \"\"\"\n        if TEMPLATE_VERSION_HEADER not in header.keys():\n            return START_TEMPLATE_VERSION\n\n        return header[TEMPLATE_VERSION_HEADER]\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.__init__","title":"__init__(self, tmp_path, template_header, template_tree, validate_yaml_header, validate_md_body, governed_section=None) special","text":"

                                                                            Initialize markdown validator.

                                                                            Source code in trestle/core/markdown/markdown_validator.py
                                                                            def __init__(\n    self,\n    tmp_path: pathlib.Path,\n    template_header: Dict,\n    template_tree: DocsMarkdownNode,\n    validate_yaml_header: bool,\n    validate_md_body: bool,\n    governed_section: Optional[str] = None\n):\n\"\"\"Initialize markdown validator.\"\"\"\n    self._validate_yaml_header = validate_yaml_header\n    self._validate_md_body = validate_md_body\n    self.governed_section = governed_section.strip(' ') if governed_section is not None else None\n    self.template_header = template_header\n    self.template_tree = template_tree\n    self.template_path = tmp_path\n    self.template_version = self.extract_template_version(self.template_header)\n\n    if self.template_version not in str(self.template_path):\n        raise TrestleError(\n            f'Version of the template {self.template_version} does not match the path {self.template_path}.'\n            + f'Move the template to the folder {self.template_version}'\n        )\n    if 'Version' in self.template_header.keys() and self.template_header['Version'] != self.template_version:\n        raise TrestleError(f'Version does not match template-version in template: {self.template_path}.')\n    self._ignore_headers = []\n    for key in self.template_header.keys():\n        if key.lower().startswith('x-trestle-'):\n            self._ignore_headers.append(key.lower())\n            if key.lower() == 'x-trestle-ignore':\n                for key2 in template_header['x-trestle-ignore']:\n                    self._ignore_headers.append(key2.lower())\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.compare_keys","title":"compare_keys(template, candidate, ignore_fields=None) classmethod","text":"

                                                                            Compare a template dictionary against a candidate as to whether key structure is maintained.

                                                                            Parameters:

                                                                            Name Type Description Default template Dict[str, Any]

                                                                            Template dict which is used as a model of key-value pairs

                                                                            required candidate Dict[str, Any]

                                                                            Candidate dictionary to be measured

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            Whether or not the the candidate matches the template keys.

                                                                            Source code in trestle/core/markdown/markdown_validator.py
                                                                            @classmethod\ndef compare_keys(\n    cls,\n    template: Dict[str, Any],\n    candidate: Dict[str, Any],\n    ignore_fields: Optional[Dict[str, Any]] = None\n) -> bool:\n\"\"\"\n    Compare a template dictionary against a candidate as to whether key structure is maintained.\n\n    Args:\n        template: Template dict which is used as a model of key-value pairs\n        candidate: Candidate dictionary to be measured\n    Returns:\n        Whether or not the the candidate matches the template keys.\n    \"\"\"\n    if ignore_fields is None:\n        ignore_fields = []\n    for key in list(candidate.keys()):\n        if key.lower() in ignore_fields:\n            candidate.pop(key)\n    for key in list(template.keys()):\n        if key.lower() in ignore_fields:\n            template.pop(key)\n    template_version = cls.extract_template_version(template)\n    candidate_version = cls.extract_template_version(candidate)\n    if template_version != candidate_version:\n        logger.info(f'Versions of the template {template_version} and instance {candidate_version} are different')\n        return False\n\n    if len(template.keys()) != len(candidate.keys()):\n        logger.info(f'Number of keys does not match in template {template} and instance {candidate}')\n        return False\n    for key in template.keys():\n        if key in candidate.keys():\n            if type(template[key]) == dict:\n                if type(candidate[key]) == dict:\n                    status = cls.compare_keys(template[key], candidate[key], ignore_fields)\n                    if not status:\n                        return status\n                else:\n                    logger.info(f'Value under {key} must be dictionary in candidate {candidate}')\n                    return False\n        else:\n            logger.info(f'Key {key} is not in candidate {candidate}')\n            return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.extract_template_version","title":"extract_template_version(header) classmethod","text":"

                                                                            Extract the template version from the header.

                                                                            If no header is found then starting version(0.0.1) will be used by default

                                                                            Source code in trestle/core/markdown/markdown_validator.py
                                                                            @classmethod\ndef extract_template_version(cls, header: Dict[str, Any]) -> Optional[str]:\n\"\"\"\n    Extract the template version from the header.\n\n    If no header is found then starting version(0.0.1) will be used by default\n    \"\"\"\n    if TEMPLATE_VERSION_HEADER not in header.keys():\n        return START_TEMPLATE_VERSION\n\n    return header[TEMPLATE_VERSION_HEADER]\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.markdown_validator/#trestle.core.markdown.markdown_validator.MarkdownValidator.is_valid_against_template","title":"is_valid_against_template(self, instance, instance_header, instance_tree)","text":"

                                                                            Validate instance markdown against template.

                                                                            Instance is correct against a template iff: 1. For YAML header keys: a. All keys from the template are present and not modified b. Template version in the template and instance match 2. On the Markdown w/o YAML header: a. No additional headers of the level 1 were added b. Headers were not reordered c. Headers in the instance should be a superset of the template headers d. Headers must be in heirarchical order (i.e. # then ### then ## is not allowed) 3. If Governed Header is given then: a. Governed Header is not modified b. All keys (i.e. key: something) inside the section are present

                                                                            Parameters:

                                                                            Name Type Description Default instance Path

                                                                            a path to the markdown instance that should be validated

                                                                            required instance_header Dict

                                                                            a YAML header extracted from the markdown

                                                                            required instance_tree DocsMarkdownNode

                                                                            a tree structure representing markdown contents

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            Whether or not the the candidate is valid against the template.

                                                                            Source code in trestle/core/markdown/markdown_validator.py
                                                                            def is_valid_against_template(\n    self, instance: pathlib.Path, instance_header: Dict, instance_tree: DocsMarkdownNode\n) -> bool:\n\"\"\"\n    Validate instance markdown against template.\n\n    Instance is correct against a template iff:\n        1. For YAML header keys:\n            a. All keys from the template are present and not modified\n            b. Template version in the template and instance match\n        2. On the Markdown w/o YAML header:\n            a. No additional headers of the level 1 were added\n            b. Headers were not reordered\n            c. Headers in the instance should be a superset of the template headers\n            d. Headers must be in heirarchical order (i.e. # then ### then ## is not allowed)\n        3. If Governed Header is given then:\n            a. Governed Header is not modified\n            b. All keys (i.e. key: something) inside the section are present\n\n    Args:\n        instance: a path to the markdown instance that should be validated\n        instance_header: a YAML header extracted from the markdown\n        instance_tree: a tree structure representing markdown contents\n    Returns:\n        Whether or not the the candidate is valid against the template.\n    \"\"\"\n    if self._validate_yaml_header:\n        headers_match = self.compare_keys(self.template_header, instance_header, self._ignore_headers)\n\n        if not headers_match:\n            logger.info(f'YAML header mismatch between template {self.template_path} and instance {instance}')\n            return False\n        elif headers_match and not self._validate_md_body:\n            return True\n\n    if self.governed_section is not None:\n        instance_gov_nodes = instance_tree.get_all_nodes_for_keys([self.governed_section], False)\n        template_gov_nodes = self.template_tree.get_all_nodes_for_keys([self.governed_section], False)\n\n        if not instance_gov_nodes:\n            logger.info(f'Governed section {self.governed_section} not found in instance: {instance}')\n            return False\n\n        if not template_gov_nodes:\n            logger.info(f'Governed section {self.governed_section} not found in template: {self.template_path}')\n            return False\n\n        if [node.key for node in instance_gov_nodes] != [node.key for node in template_gov_nodes]:\n            logger.info(\n                f'Governed sections were changed, '\n                f'template expects: {[node.key for node in template_gov_nodes]},'\n                f'but found {[node.key for node in instance_gov_nodes]}.'\n            )\n            return False\n\n        for instance_gov_node, template_gov_node in zip(instance_gov_nodes, template_gov_nodes):\n            instance_keys = instance_gov_node.content.governed_document\n            template_keys = template_gov_node.content.governed_document\n\n            is_valid = self._validate_headings(instance, template_keys, instance_keys)\n            if not is_valid:\n                return False\n\n    if self._validate_md_body:\n        instance_keys = instance_tree.content.subnodes_keys\n        template_keys = self.template_tree.content.subnodes_keys\n        if len(template_keys) > len(instance_keys):\n            logger.info(f'Headings in the instance: {instance} were removed.')\n            return False\n\n        instance_lvl1_keys = list(instance_tree.get_all_headers_for_level(1))\n        template_lvl1_keys = list(self.template_tree.get_all_headers_for_level(1))\n        if len(template_lvl1_keys) < len(instance_lvl1_keys):\n            logger.info(f'New headers of level 1 were added to the markdown instance: {instance}. ')\n            return False\n\n        is_valid = self._validate_headings(instance, template_keys, instance_keys)\n        if not is_valid:\n            return False\n\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/","title":"md_writer","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer","title":"trestle.core.markdown.md_writer","text":"

                                                                            Create formatted markdown files with optional yaml header.

                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter","title":" MDWriter ","text":"

                                                                            Simple class to create markdown files.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            class MDWriter():\n\"\"\"Simple class to create markdown files.\"\"\"\n\n    def __init__(self, file_path: pathlib.Path, header_comments_dict: Optional[Dict[str, str]] = None):\n\"\"\"Initialize the class.\"\"\"\n        self._file_path = file_path\n        self._lines = []\n        self._indent_level = 0\n        self._indent_size = 2\n        self._yaml_header = None\n        self._header_comments_dict = header_comments_dict\n\n    def _current_indent_space(self):\n        if self._indent_level <= 0:\n            return ''\n        return ' ' * (self._indent_level * self._indent_size)\n\n    def _add_line_raw(self, line: str) -> None:\n        out_line = '' if self._is_blank(line) else line\n        self._lines.append(out_line)\n\n    def _add_indent_level(self, delta: int) -> None:\n        self._indent_level += delta\n\n    def exists(self) -> bool:\n\"\"\"Check if the file already exists.\"\"\"\n        return self._file_path.exists()\n\n    def add_yaml_header(self, header: dict) -> None:\n\"\"\"Add the yaml header.\"\"\"\n        self._yaml_header = header\n\n    def set_indent_level(self, level: int) -> None:\n\"\"\"Set the current indent level.\"\"\"\n        self._indent_level = level\n\n    def set_indent_step_size(self, size: int) -> None:\n\"\"\"Set the indent step size in spaces.\"\"\"\n        self._indent_size = size\n\n    def _is_blank(self, line: str) -> bool:\n        return line.strip() == ''\n\n    def _prev_blank_line(self) -> bool:\n        return len(self._lines) > 0 and self._is_blank(self._lines[-1])\n\n    def new_line(self, line: str) -> None:\n\"\"\"Add a line of text to the output.\"\"\"\n        # prevent double empty lines\n        out_line = '' if self._is_blank(line) else self._current_indent_space() + line\n        if self._prev_blank_line() and out_line == '':\n            return\n        self._add_line_raw(out_line)\n\n    def new_paraline(self, line: str) -> None:\n\"\"\"Add a paragraph and a line to output.\"\"\"\n        self.new_paragraph()\n        self.new_line(line)\n\n    def new_paragraph(self):\n\"\"\"Start a new paragraph.\"\"\"\n        self.new_line('')\n\n    def new_header(self, level: int, title: str, add_new_line_after_header: bool = True) -> None:\n\"\"\"Add new header.\"\"\"\n        # headers might be separated by blank lines\n        self.new_paragraph()\n        self.new_line('#' * level + ' ' + title)\n        if add_new_line_after_header:\n            self.new_paragraph()\n\n    def new_hr(self) -> None:\n\"\"\"Add horizontal rule.\"\"\"\n        self.new_paragraph()\n        self.new_line(const.SSP_MD_HRULE_LINE)\n        self.new_paragraph()\n\n    def new_list(self, list_: List[Any]) -> None:\n\"\"\"Add a list to the markdown.\"\"\"\n        # in general this is a list of lists\n        # if string just write it out\n        if isinstance(list_, str):\n            if self._is_blank(list_):\n                self.new_paragraph()\n            else:\n                self.new_line('- ' + list_)\n        # else it is a sublist so indent\n        else:\n            self._add_indent_level(1)\n            self.new_paragraph()\n            for item in list_:\n                if self._indent_level <= 0:\n                    self.new_paragraph()\n                self.new_list(item)\n            self._add_indent_level(-1)\n\n    def new_table(self, table_list: List[List[str]], header: List[str]):\n\"\"\"Add table to the markdown. All rows must be of equal length.\"\"\"\n        header_str = '| ' + ' | '.join(header) + ' |'\n        sep_str = '|---' * len(header) + '|'\n        self.new_line(header_str)\n        self.new_line(sep_str)\n        for row in table_list:\n            row_str = '| ' + ' | '.join(row) + ' |'\n            self.new_line(row_str)\n\n    def _check_header(self) -> None:\n        while len(self._lines) > 0 and self._lines[0] == '':\n            self._lines = self._lines[1:]\n\n    def write_out(self) -> None:\n\"\"\"Write out the markdown file.\"\"\"\n        self._check_header()\n        try:\n            self._file_path.parent.mkdir(exist_ok=True, parents=True)\n            with open(self._file_path, 'w', encoding=const.FILE_ENCODING) as f:\n                # Make sure yaml header is written first\n                if self._yaml_header:\n                    f.write('---\\n')\n                    yaml = YAML()\n                    yaml.indent(mapping=2, sequence=4, offset=2)\n                    yaml.dump(self._yaml_header, f)\n                    f.write('---\\n\\n')\n\n                f.write('\\n'.join(self._lines))\n                # if last line has text it will need an extra \\n at end\n                if self._lines and self._lines[-1]:\n                    f.write('\\n')\n            # insert helpful comments into the header happens after header is written out\n            for tag, comment in as_dict(self._header_comments_dict).items():\n                if tag in as_dict(self._yaml_header):\n                    file_utils.insert_text_in_file(self._file_path, tag, comment)\n        except IOError as e:\n            logger.debug(f'md_writer error attempting to write out md file {self._file_path} {e}')\n            raise TrestleError(f'Error attempting to write out md file {self._file_path} {e}')\n\n    def get_lines(self) -> List[str]:\n\"\"\"Return the current lines in the file.\"\"\"\n        return self._lines\n\n    def get_text(self) -> str:\n\"\"\"Get the text as currently written.\"\"\"\n        return '\\n'.join(self._lines)\n\n    def cull_headings(self, md_in: pathlib.Path, cull_list: List[str], strict_match: bool = False) -> None:\n\"\"\"\n        Cull headers from the lines of input markdown file with optional strict string match.\n\n        Args:\n            md_in: the path of the markdown file being edited\n            cull_list: the list of strings in headers that are to be culled\n            strict_match: whether to require an exact string match on header key or just a substring\n\n        Returns None and creates new markdown at the path specified during MDWriter construction\n        It is allowed to overwrite the original file\n        \"\"\"\n        markdown_api = MarkdownAPI()\n        header, content = markdown_api.processor.process_markdown(md_in)\n        self._yaml_header = header\n        self._lines = content.delete_nodes_text(cull_list, strict_match)\n        self.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.__init__","title":"__init__(self, file_path, header_comments_dict=None) special","text":"

                                                                            Initialize the class.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def __init__(self, file_path: pathlib.Path, header_comments_dict: Optional[Dict[str, str]] = None):\n\"\"\"Initialize the class.\"\"\"\n    self._file_path = file_path\n    self._lines = []\n    self._indent_level = 0\n    self._indent_size = 2\n    self._yaml_header = None\n    self._header_comments_dict = header_comments_dict\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.add_yaml_header","title":"add_yaml_header(self, header)","text":"

                                                                            Add the yaml header.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def add_yaml_header(self, header: dict) -> None:\n\"\"\"Add the yaml header.\"\"\"\n    self._yaml_header = header\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.cull_headings","title":"cull_headings(self, md_in, cull_list, strict_match=False)","text":"

                                                                            Cull headers from the lines of input markdown file with optional strict string match.

                                                                            Parameters:

                                                                            Name Type Description Default md_in Path

                                                                            the path of the markdown file being edited

                                                                            required cull_list List[str]

                                                                            the list of strings in headers that are to be culled

                                                                            required strict_match bool

                                                                            whether to require an exact string match on header key or just a substring

                                                                            False

                                                                            Returns None and creates new markdown at the path specified during MDWriter construction It is allowed to overwrite the original file

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def cull_headings(self, md_in: pathlib.Path, cull_list: List[str], strict_match: bool = False) -> None:\n\"\"\"\n    Cull headers from the lines of input markdown file with optional strict string match.\n\n    Args:\n        md_in: the path of the markdown file being edited\n        cull_list: the list of strings in headers that are to be culled\n        strict_match: whether to require an exact string match on header key or just a substring\n\n    Returns None and creates new markdown at the path specified during MDWriter construction\n    It is allowed to overwrite the original file\n    \"\"\"\n    markdown_api = MarkdownAPI()\n    header, content = markdown_api.processor.process_markdown(md_in)\n    self._yaml_header = header\n    self._lines = content.delete_nodes_text(cull_list, strict_match)\n    self.write_out()\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.exists","title":"exists(self)","text":"

                                                                            Check if the file already exists.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def exists(self) -> bool:\n\"\"\"Check if the file already exists.\"\"\"\n    return self._file_path.exists()\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.get_lines","title":"get_lines(self)","text":"

                                                                            Return the current lines in the file.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def get_lines(self) -> List[str]:\n\"\"\"Return the current lines in the file.\"\"\"\n    return self._lines\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.get_text","title":"get_text(self)","text":"

                                                                            Get the text as currently written.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def get_text(self) -> str:\n\"\"\"Get the text as currently written.\"\"\"\n    return '\\n'.join(self._lines)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_header","title":"new_header(self, level, title, add_new_line_after_header=True)","text":"

                                                                            Add new header.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def new_header(self, level: int, title: str, add_new_line_after_header: bool = True) -> None:\n\"\"\"Add new header.\"\"\"\n    # headers might be separated by blank lines\n    self.new_paragraph()\n    self.new_line('#' * level + ' ' + title)\n    if add_new_line_after_header:\n        self.new_paragraph()\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_hr","title":"new_hr(self)","text":"

                                                                            Add horizontal rule.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def new_hr(self) -> None:\n\"\"\"Add horizontal rule.\"\"\"\n    self.new_paragraph()\n    self.new_line(const.SSP_MD_HRULE_LINE)\n    self.new_paragraph()\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_line","title":"new_line(self, line)","text":"

                                                                            Add a line of text to the output.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def new_line(self, line: str) -> None:\n\"\"\"Add a line of text to the output.\"\"\"\n    # prevent double empty lines\n    out_line = '' if self._is_blank(line) else self._current_indent_space() + line\n    if self._prev_blank_line() and out_line == '':\n        return\n    self._add_line_raw(out_line)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_list","title":"new_list(self, list_)","text":"

                                                                            Add a list to the markdown.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def new_list(self, list_: List[Any]) -> None:\n\"\"\"Add a list to the markdown.\"\"\"\n    # in general this is a list of lists\n    # if string just write it out\n    if isinstance(list_, str):\n        if self._is_blank(list_):\n            self.new_paragraph()\n        else:\n            self.new_line('- ' + list_)\n    # else it is a sublist so indent\n    else:\n        self._add_indent_level(1)\n        self.new_paragraph()\n        for item in list_:\n            if self._indent_level <= 0:\n                self.new_paragraph()\n            self.new_list(item)\n        self._add_indent_level(-1)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_paragraph","title":"new_paragraph(self)","text":"

                                                                            Start a new paragraph.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def new_paragraph(self):\n\"\"\"Start a new paragraph.\"\"\"\n    self.new_line('')\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_paraline","title":"new_paraline(self, line)","text":"

                                                                            Add a paragraph and a line to output.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def new_paraline(self, line: str) -> None:\n\"\"\"Add a paragraph and a line to output.\"\"\"\n    self.new_paragraph()\n    self.new_line(line)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.new_table","title":"new_table(self, table_list, header)","text":"

                                                                            Add table to the markdown. All rows must be of equal length.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def new_table(self, table_list: List[List[str]], header: List[str]):\n\"\"\"Add table to the markdown. All rows must be of equal length.\"\"\"\n    header_str = '| ' + ' | '.join(header) + ' |'\n    sep_str = '|---' * len(header) + '|'\n    self.new_line(header_str)\n    self.new_line(sep_str)\n    for row in table_list:\n        row_str = '| ' + ' | '.join(row) + ' |'\n        self.new_line(row_str)\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.set_indent_level","title":"set_indent_level(self, level)","text":"

                                                                            Set the current indent level.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def set_indent_level(self, level: int) -> None:\n\"\"\"Set the current indent level.\"\"\"\n    self._indent_level = level\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.set_indent_step_size","title":"set_indent_step_size(self, size)","text":"

                                                                            Set the indent step size in spaces.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def set_indent_step_size(self, size: int) -> None:\n\"\"\"Set the indent step size in spaces.\"\"\"\n    self._indent_size = size\n
                                                                            "},{"location":"api_reference/trestle.core.markdown.md_writer/#trestle.core.markdown.md_writer.MDWriter.write_out","title":"write_out(self)","text":"

                                                                            Write out the markdown file.

                                                                            Source code in trestle/core/markdown/md_writer.py
                                                                            def write_out(self) -> None:\n\"\"\"Write out the markdown file.\"\"\"\n    self._check_header()\n    try:\n        self._file_path.parent.mkdir(exist_ok=True, parents=True)\n        with open(self._file_path, 'w', encoding=const.FILE_ENCODING) as f:\n            # Make sure yaml header is written first\n            if self._yaml_header:\n                f.write('---\\n')\n                yaml = YAML()\n                yaml.indent(mapping=2, sequence=4, offset=2)\n                yaml.dump(self._yaml_header, f)\n                f.write('---\\n\\n')\n\n            f.write('\\n'.join(self._lines))\n            # if last line has text it will need an extra \\n at end\n            if self._lines and self._lines[-1]:\n                f.write('\\n')\n        # insert helpful comments into the header happens after header is written out\n        for tag, comment in as_dict(self._header_comments_dict).items():\n            if tag in as_dict(self._yaml_header):\n                file_utils.insert_text_in_file(self._file_path, tag, comment)\n    except IOError as e:\n        logger.debug(f'md_writer error attempting to write out md file {self._file_path} {e}')\n        raise TrestleError(f'Error attempting to write out md file {self._file_path} {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/","title":"actions","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions","title":"trestle.core.models.actions","text":"

                                                                            Action wrapper of a command.

                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action","title":" Action (ABC) ","text":"

                                                                            Action wrapper of a command.

                                                                            Source code in trestle/core/models/actions.py
                                                                            class Action(ABC):\n\"\"\"Action wrapper of a command.\"\"\"\n\n    def __init__(self, action_type: ActionType, has_rollback: bool) -> None:\n\"\"\"Initialize an base action.\"\"\"\n        self._type: ActionType = action_type\n        self._has_rollback: bool = has_rollback\n\n        # child class must set this flag once it executes\n        self._has_executed = False\n\n    def to_string(self) -> str:\n\"\"\"Return a string representation.\"\"\"\n        return self.__str__()\n\n    def get_type(self) -> ActionType:\n\"\"\"Return the action type.\"\"\"\n        return self._type\n\n    def _mark_executed(self) -> None:\n\"\"\"Set flag that the action has been executed.\"\"\"\n        self._has_executed = True\n\n    def has_executed(self) -> bool:\n\"\"\"Return if the action has been executed.\"\"\"\n        return self._has_executed\n\n    def _mark_rollback(self) -> None:\n\"\"\"Set flag that the action has been rollbacked.\"\"\"\n        self._has_executed = False\n\n    def has_rollback(self) -> bool:\n\"\"\"Return if rollback of the action is possible.\"\"\"\n        return self._has_rollback\n\n    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two actions are equal.\"\"\"\n        if not isinstance(other, Action):\n            return False\n        if self.get_type() is not other.get_type():\n            return False\n        is_eq = self.__dict__ == other.__dict__\n        return is_eq\n\n    @abstractmethod\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n\n    @abstractmethod\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.__eq__","title":"__eq__(self, other) special","text":"

                                                                            Check that two actions are equal.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __eq__(self, other: object) -> bool:\n\"\"\"Check that two actions are equal.\"\"\"\n    if not isinstance(other, Action):\n        return False\n    if self.get_type() is not other.get_type():\n        return False\n    is_eq = self.__dict__ == other.__dict__\n    return is_eq\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.__init__","title":"__init__(self, action_type, has_rollback) special","text":"

                                                                            Initialize an base action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __init__(self, action_type: ActionType, has_rollback: bool) -> None:\n\"\"\"Initialize an base action.\"\"\"\n    self._type: ActionType = action_type\n    self._has_rollback: bool = has_rollback\n\n    # child class must set this flag once it executes\n    self._has_executed = False\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.execute","title":"execute(self)","text":"

                                                                            Execute the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            @abstractmethod\ndef execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.get_type","title":"get_type(self)","text":"

                                                                            Return the action type.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def get_type(self) -> ActionType:\n\"\"\"Return the action type.\"\"\"\n    return self._type\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.has_executed","title":"has_executed(self)","text":"

                                                                            Return if the action has been executed.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def has_executed(self) -> bool:\n\"\"\"Return if the action has been executed.\"\"\"\n    return self._has_executed\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.has_rollback","title":"has_rollback(self)","text":"

                                                                            Return if rollback of the action is possible.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def has_rollback(self) -> bool:\n\"\"\"Return if rollback of the action is possible.\"\"\"\n    return self._has_rollback\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.rollback","title":"rollback(self)","text":"

                                                                            Rollback the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            @abstractmethod\ndef rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.Action.to_string","title":"to_string(self)","text":"

                                                                            Return a string representation.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def to_string(self) -> str:\n\"\"\"Return a string representation.\"\"\"\n    return self.__str__()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType","title":" ActionType (Enum) ","text":"

                                                                            Action type enum for different action type.

                                                                            File system related actions have code like 1 Model processing related actions have code like 2

                                                                            Source code in trestle/core/models/actions.py
                                                                            class ActionType(Enum):\n\"\"\"Action type enum for different action type.\n\n    File system related actions have code like 1*\n    Model processing related actions have code like 2*\n    \"\"\"\n\n    # create a file or directory path\n    CREATE_PATH = 10\n\n    # remove a file or directory path\n    REMOVE_PATH = 12\n\n    # write element to a destination file or stream\n    WRITE = 11\n\n    # update or add the element at the path\n    UPDATE = 20\n\n    # remove the element at the path\n    REMOVE = 21\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.CREATE_PATH","title":"CREATE_PATH","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.REMOVE","title":"REMOVE","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.REMOVE_PATH","title":"REMOVE_PATH","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.UPDATE","title":"UPDATE","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.ActionType.WRITE","title":"WRITE","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction","title":" CreatePathAction (Action) ","text":"

                                                                            Create a file or directory path.

                                                                            Source code in trestle/core/models/actions.py
                                                                            class CreatePathAction(Action):\n\"\"\"Create a file or directory path.\"\"\"\n\n    def __init__(self, sub_path: pathlib.Path, clear_content: bool = False) -> None:\n\"\"\"Initialize a create path action.\n\n        It creates all the missing directories in the path.\n        If it is a file, then it also creates an empty file with the name provided\n\n        Arguments:\n            sub_path: this is the desired file or directory path that needs to be created under the project root\n        \"\"\"\n        sub_path = sub_path.resolve()\n\n        self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n        if self._trestle_project_root is None:\n            raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project')\n\n        self._sub_path = sub_path\n        self._created_paths: List[pathlib.Path] = []\n\n        # variables for handling with file content\n        self._clear_content = clear_content\n        self._old_file_content = None\n\n        super().__init__(ActionType.CREATE_PATH, True)\n\n    def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n        return self._trestle_project_root\n\n    def get_created_paths(self) -> List[pathlib.Path]:\n\"\"\"Get the list of paths that were created after being executed.\"\"\"\n        return self._created_paths\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        # find the start of the sub_path relative to trestle project root\n        cur_index = len(self._trestle_project_root.parts)\n\n        # loop through the sub_path parts and create as necessary\n        cur_path = self._trestle_project_root\n        while cur_index < len(self._sub_path.parts):\n            part = self._sub_path.parts[cur_index]\n\n            # create a path relative to the current\n            # it starts with the project root, so we shall always create\n            # sub directories or files relative to the project root\n            cur_path = cur_path / part  # type: ignore\n\n            # create the sub_path file or directory if it does not exists already\n            if cur_path.suffix != '':  # suffix will denote a file\n                if not cur_path.exists():\n                    # create file\n                    cur_path.touch()\n\n                    # add in the list for rollback\n                    self._created_paths.append(cur_path)\n                elif self._clear_content:\n                    # read file content for rollback\n                    with open(cur_path, 'r+', encoding=const.FILE_ENCODING) as fp:\n                        # read all content\n                        self._old_file_content = fp.read()\n\n                        # clear file content\n                        fp.truncate(0)\n            else:\n                if not cur_path.exists():\n                    # create directory\n                    cur_path.mkdir()\n\n                    # add in the list for rollback\n                    self._created_paths.append(cur_path)\n\n            # move to the next part of the sub_path parts\n            cur_index = cur_index + 1\n\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            if len(self._created_paths) > 0:\n                for cur_path in reversed(self._created_paths):\n                    if cur_path.exists():\n                        if cur_path.is_file():\n                            cur_path.unlink()\n                        elif cur_path.is_dir():\n                            cur_path.rmdir()\n\n                self._created_paths.clear()\n\n            # rollback the content of a file if required\n            # we should be here only if there were no path created and the sub_part already existed\n            elif self._sub_path.is_file() and self._sub_path.exists() and self._clear_content is True:\n                if self._old_file_content is not None:\n                    with open(self._sub_path, 'w', encoding=const.FILE_ENCODING) as fp:\n                        fp.write(self._old_file_content)\n\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._sub_path}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.__init__","title":"__init__(self, sub_path, clear_content=False) special","text":"

                                                                            Initialize a create path action.

                                                                            It creates all the missing directories in the path. If it is a file, then it also creates an empty file with the name provided

                                                                            Parameters:

                                                                            Name Type Description Default sub_path Path

                                                                            this is the desired file or directory path that needs to be created under the project root

                                                                            required Source code in trestle/core/models/actions.py
                                                                            def __init__(self, sub_path: pathlib.Path, clear_content: bool = False) -> None:\n\"\"\"Initialize a create path action.\n\n    It creates all the missing directories in the path.\n    If it is a file, then it also creates an empty file with the name provided\n\n    Arguments:\n        sub_path: this is the desired file or directory path that needs to be created under the project root\n    \"\"\"\n    sub_path = sub_path.resolve()\n\n    self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n    if self._trestle_project_root is None:\n        raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project')\n\n    self._sub_path = sub_path\n    self._created_paths: List[pathlib.Path] = []\n\n    # variables for handling with file content\n    self._clear_content = clear_content\n    self._old_file_content = None\n\n    super().__init__(ActionType.CREATE_PATH, True)\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.__str__","title":"__str__(self) special","text":"

                                                                            Return string representation.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._sub_path}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.execute","title":"execute(self)","text":"

                                                                            Execute the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    # find the start of the sub_path relative to trestle project root\n    cur_index = len(self._trestle_project_root.parts)\n\n    # loop through the sub_path parts and create as necessary\n    cur_path = self._trestle_project_root\n    while cur_index < len(self._sub_path.parts):\n        part = self._sub_path.parts[cur_index]\n\n        # create a path relative to the current\n        # it starts with the project root, so we shall always create\n        # sub directories or files relative to the project root\n        cur_path = cur_path / part  # type: ignore\n\n        # create the sub_path file or directory if it does not exists already\n        if cur_path.suffix != '':  # suffix will denote a file\n            if not cur_path.exists():\n                # create file\n                cur_path.touch()\n\n                # add in the list for rollback\n                self._created_paths.append(cur_path)\n            elif self._clear_content:\n                # read file content for rollback\n                with open(cur_path, 'r+', encoding=const.FILE_ENCODING) as fp:\n                    # read all content\n                    self._old_file_content = fp.read()\n\n                    # clear file content\n                    fp.truncate(0)\n        else:\n            if not cur_path.exists():\n                # create directory\n                cur_path.mkdir()\n\n                # add in the list for rollback\n                self._created_paths.append(cur_path)\n\n        # move to the next part of the sub_path parts\n        cur_index = cur_index + 1\n\n    self._mark_executed()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.get_created_paths","title":"get_created_paths(self)","text":"

                                                                            Get the list of paths that were created after being executed.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def get_created_paths(self) -> List[pathlib.Path]:\n\"\"\"Get the list of paths that were created after being executed.\"\"\"\n    return self._created_paths\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.get_trestle_project_root","title":"get_trestle_project_root(self)","text":"

                                                                            Return the trestle workspace root path.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n    return self._trestle_project_root\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.CreatePathAction.rollback","title":"rollback(self)","text":"

                                                                            Rollback the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        if len(self._created_paths) > 0:\n            for cur_path in reversed(self._created_paths):\n                if cur_path.exists():\n                    if cur_path.is_file():\n                        cur_path.unlink()\n                    elif cur_path.is_dir():\n                        cur_path.rmdir()\n\n            self._created_paths.clear()\n\n        # rollback the content of a file if required\n        # we should be here only if there were no path created and the sub_part already existed\n        elif self._sub_path.is_file() and self._sub_path.exists() and self._clear_content is True:\n            if self._old_file_content is not None:\n                with open(self._sub_path, 'w', encoding=const.FILE_ENCODING) as fp:\n                    fp.write(self._old_file_content)\n\n    self._mark_rollback()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction","title":" RemoveAction (Action) ","text":"

                                                                            Remove sub element at the element path in the source element.

                                                                            Source code in trestle/core/models/actions.py
                                                                            class RemoveAction(Action):\n\"\"\"Remove sub element at the element path in the source element.\"\"\"\n\n    def __init__(self, src_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize a remove element action.\"\"\"\n        super().__init__(ActionType.REMOVE, True)\n\n        self._src_element: Element = src_element\n        self._sub_element_path: ElementPath = sub_element_path\n        self._prev_sub_element = None\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        self._prev_sub_element = self._src_element.get_at(self._sub_element_path)\n        self._src_element.set_at(self._sub_element_path, None)\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            self._src_element.set_at(self._sub_element_path, self._prev_sub_element)\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} element at {self._sub_element_path} from {self._src_element}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.__init__","title":"__init__(self, src_element, sub_element_path) special","text":"

                                                                            Initialize a remove element action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __init__(self, src_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize a remove element action.\"\"\"\n    super().__init__(ActionType.REMOVE, True)\n\n    self._src_element: Element = src_element\n    self._sub_element_path: ElementPath = sub_element_path\n    self._prev_sub_element = None\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.__str__","title":"__str__(self) special","text":"

                                                                            Return string representation.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} element at {self._sub_element_path} from {self._src_element}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.execute","title":"execute(self)","text":"

                                                                            Execute the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    self._prev_sub_element = self._src_element.get_at(self._sub_element_path)\n    self._src_element.set_at(self._sub_element_path, None)\n    self._mark_executed()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemoveAction.rollback","title":"rollback(self)","text":"

                                                                            Rollback the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        self._src_element.set_at(self._sub_element_path, self._prev_sub_element)\n    self._mark_rollback()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction","title":" RemovePathAction (Action) ","text":"

                                                                            Remove a file or directory path.

                                                                            Source code in trestle/core/models/actions.py
                                                                            class RemovePathAction(Action):\n\"\"\"Remove a file or directory path.\"\"\"\n\n    def __init__(self, sub_path: pathlib.Path) -> None:\n\"\"\"Initialize a remove path action.\n\n        It removes the file or directory recursively into trash.\n\n        Arguments:\n            sub_path: this is the desired file or directory path that needs to be removed under the project root\n        \"\"\"\n        if not isinstance(sub_path, pathlib.Path):\n            raise TrestleError('Sub path must be of type pathlib.Path')\n\n        self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n        if self._trestle_project_root is None:\n            raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project.')\n\n        self._sub_path = sub_path\n\n        super().__init__(ActionType.REMOVE_PATH, True)\n\n    def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n        return self._trestle_project_root\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        if not self._sub_path.exists():\n            logger.debug(f'path {self._sub_path} does not exist in remove path action - ignoring.')\n\n        trash.store(self._sub_path, True)\n\n        # check if parent folder is empty and if so delete\n        parent_dir = pathlib.Path(os.path.dirname(self._sub_path))\n        files = list(parent_dir.iterdir())\n        if not files:\n            trash.store(parent_dir, True)\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            trash_path = trash.to_trash_path(self._sub_path)\n            if trash_path is None or trash_path.exists() is False:\n                # FIXME suppress file contents not found message til trash/rollback behavior is fixed.  # issue 412\n                return\n            trash.recover(self._sub_path, True)\n\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._sub_path}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.__init__","title":"__init__(self, sub_path) special","text":"

                                                                            Initialize a remove path action.

                                                                            It removes the file or directory recursively into trash.

                                                                            Parameters:

                                                                            Name Type Description Default sub_path Path

                                                                            this is the desired file or directory path that needs to be removed under the project root

                                                                            required Source code in trestle/core/models/actions.py
                                                                            def __init__(self, sub_path: pathlib.Path) -> None:\n\"\"\"Initialize a remove path action.\n\n    It removes the file or directory recursively into trash.\n\n    Arguments:\n        sub_path: this is the desired file or directory path that needs to be removed under the project root\n    \"\"\"\n    if not isinstance(sub_path, pathlib.Path):\n        raise TrestleError('Sub path must be of type pathlib.Path')\n\n    self._trestle_project_root = file_utils.extract_trestle_project_root(sub_path)\n    if self._trestle_project_root is None:\n        raise TrestleError(f'Sub path \"{sub_path}\" should be child of a valid trestle project.')\n\n    self._sub_path = sub_path\n\n    super().__init__(ActionType.REMOVE_PATH, True)\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.__str__","title":"__str__(self) special","text":"

                                                                            Return string representation.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._sub_path}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.execute","title":"execute(self)","text":"

                                                                            Execute the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    if not self._sub_path.exists():\n        logger.debug(f'path {self._sub_path} does not exist in remove path action - ignoring.')\n\n    trash.store(self._sub_path, True)\n\n    # check if parent folder is empty and if so delete\n    parent_dir = pathlib.Path(os.path.dirname(self._sub_path))\n    files = list(parent_dir.iterdir())\n    if not files:\n        trash.store(parent_dir, True)\n    self._mark_executed()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.get_trestle_project_root","title":"get_trestle_project_root(self)","text":"

                                                                            Return the trestle workspace root path.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def get_trestle_project_root(self) -> Optional[pathlib.Path]:\n\"\"\"Return the trestle workspace root path.\"\"\"\n    return self._trestle_project_root\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.RemovePathAction.rollback","title":"rollback(self)","text":"

                                                                            Rollback the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        trash_path = trash.to_trash_path(self._sub_path)\n        if trash_path is None or trash_path.exists() is False:\n            # FIXME suppress file contents not found message til trash/rollback behavior is fixed.  # issue 412\n            return\n        trash.recover(self._sub_path, True)\n\n    self._mark_rollback()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction","title":" UpdateAction (Action) ","text":"

                                                                            Update element at the element path in the destination element with the source element.

                                                                            Source code in trestle/core/models/actions.py
                                                                            class UpdateAction(Action):\n\"\"\"Update element at the element path in the destination element with the source element.\"\"\"\n\n    def __init__(self, sub_element, dest_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize an add element action.\n\n        Sub element can be OscalBaseModel, Element, list or None\n        \"\"\"\n        super().__init__(ActionType.UPDATE, True)\n\n        if not Element.is_allowed_sub_element_type(sub_element):\n            allowed_types = Element.get_allowed_sub_element_types()\n            raise TrestleError(\n                f'Sub element \"{sub_element.__class__} is not a allowed sub element types in \"{allowed_types}\"'\n            )\n\n        self._sub_element = sub_element\n        self._dest_element: Element = dest_element\n        self._sub_element_path: ElementPath = sub_element_path\n        self._prev_sub_element = None\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        self._prev_sub_element = self._dest_element.get_at(self._sub_element_path)\n        self._dest_element.set_at(self._sub_element_path, self._sub_element)\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if self.has_executed():\n            self._dest_element.set_at(self._sub_element_path, self._prev_sub_element)\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._model_obj.__class__} to {self._dest_element} at {self._sub_element_path}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.__init__","title":"__init__(self, sub_element, dest_element, sub_element_path) special","text":"

                                                                            Initialize an add element action.

                                                                            Sub element can be OscalBaseModel, Element, list or None

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __init__(self, sub_element, dest_element: Element, sub_element_path: ElementPath) -> None:\n\"\"\"Initialize an add element action.\n\n    Sub element can be OscalBaseModel, Element, list or None\n    \"\"\"\n    super().__init__(ActionType.UPDATE, True)\n\n    if not Element.is_allowed_sub_element_type(sub_element):\n        allowed_types = Element.get_allowed_sub_element_types()\n        raise TrestleError(\n            f'Sub element \"{sub_element.__class__} is not a allowed sub element types in \"{allowed_types}\"'\n        )\n\n    self._sub_element = sub_element\n    self._dest_element: Element = dest_element\n    self._sub_element_path: ElementPath = sub_element_path\n    self._prev_sub_element = None\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.__str__","title":"__str__(self) special","text":"

                                                                            Return string representation.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._model_obj.__class__} to {self._dest_element} at {self._sub_element_path}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.execute","title":"execute(self)","text":"

                                                                            Execute the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    self._prev_sub_element = self._dest_element.get_at(self._sub_element_path)\n    self._dest_element.set_at(self._sub_element_path, self._sub_element)\n    self._mark_executed()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.UpdateAction.rollback","title":"rollback(self)","text":"

                                                                            Rollback the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if self.has_executed():\n        self._dest_element.set_at(self._sub_element_path, self._prev_sub_element)\n    self._mark_rollback()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction","title":" WriteAction (Action) ","text":"

                                                                            Write the element to a destination stream.

                                                                            Source code in trestle/core/models/actions.py
                                                                            class WriteAction(Action):\n\"\"\"Write the element to a destination stream.\"\"\"\n\n    def __init__(self, writer: Optional[io.TextIOWrapper], element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize an write file action.\"\"\"\n        super().__init__(ActionType.WRITE, True)\n\n        if writer is not None and not issubclass(io.TextIOWrapper, writer.__class__):\n            raise TrestleError(f'Writer must be of io.TextIOWrapper, given f{writer.__class__}')\n\n        self._writer: Optional[io.TextIOWrapper] = writer\n        self._element: Element = element\n        self._content_type: FileContentType = content_type\n        self._lastStreamPos = -1\n        if self._writer is not None:\n            self._lastStreamPos = self._writer.tell()\n\n    def _is_writer_valid(self) -> bool:\n        if self._writer is not None and isinstance(self._writer, io.TextIOWrapper) and not self._writer.closed:\n            return True\n\n        return False\n\n    def _encode(self) -> str:\n\"\"\"Encode the element to appropriate content type.\"\"\"\n        if self._content_type == FileContentType.YAML:\n            return self._element.to_yaml()\n        if self._content_type == FileContentType.JSON:\n            return self._element.to_json()\n\n        raise TrestleError(f'Invalid content type {self._content_type}')\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        if self._element is None:\n            raise TrestleError('Element is empty and cannot write')\n\n        if not self._is_writer_valid():\n            raise TrestleError('Writer is not provided or closed')\n\n        self._writer.write(self._encode())\n        self._writer.flush()\n        self._mark_executed()\n\n    def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n        if not self._is_writer_valid():\n            raise TrestleError('Writer is not provided or closed')\n\n        if self._lastStreamPos < 0:\n            raise TrestleError('Last stream position is not available to rollback to')\n\n        if self.has_executed():\n            self._writer.seek(self._lastStreamPos)\n            self._writer.truncate()\n\n        self._mark_rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self.get_type()} {self._element}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.__init__","title":"__init__(self, writer, element, content_type) special","text":"

                                                                            Initialize an write file action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __init__(self, writer: Optional[io.TextIOWrapper], element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize an write file action.\"\"\"\n    super().__init__(ActionType.WRITE, True)\n\n    if writer is not None and not issubclass(io.TextIOWrapper, writer.__class__):\n        raise TrestleError(f'Writer must be of io.TextIOWrapper, given f{writer.__class__}')\n\n    self._writer: Optional[io.TextIOWrapper] = writer\n    self._element: Element = element\n    self._content_type: FileContentType = content_type\n    self._lastStreamPos = -1\n    if self._writer is not None:\n        self._lastStreamPos = self._writer.tell()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.__str__","title":"__str__(self) special","text":"

                                                                            Return string representation.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self.get_type()} {self._element}'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.execute","title":"execute(self)","text":"

                                                                            Execute the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    if self._element is None:\n        raise TrestleError('Element is empty and cannot write')\n\n    if not self._is_writer_valid():\n        raise TrestleError('Writer is not provided or closed')\n\n    self._writer.write(self._encode())\n    self._writer.flush()\n    self._mark_executed()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteAction.rollback","title":"rollback(self)","text":"

                                                                            Rollback the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def rollback(self) -> None:\n\"\"\"Rollback the action.\"\"\"\n    if not self._is_writer_valid():\n        raise TrestleError('Writer is not provided or closed')\n\n    if self._lastStreamPos < 0:\n        raise TrestleError('Last stream position is not available to rollback to')\n\n    if self.has_executed():\n        self._writer.seek(self._lastStreamPos)\n        self._writer.truncate()\n\n    self._mark_rollback()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction","title":" WriteFileAction (WriteAction) ","text":"

                                                                            Write the element to a destination file.

                                                                            Source code in trestle/core/models/actions.py
                                                                            class WriteFileAction(WriteAction):\n\"\"\"Write the element to a destination file.\"\"\"\n\n    def __init__(self, file_path: pathlib.Path, element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize a write file action.\n\n        It opens the file in append mode. Therefore the file needs to exist even if it is a new file.\n        \"\"\"\n        if not isinstance(file_path, pathlib.Path):\n            raise TrestleError('file_path should be of type pathlib.Path')\n\n        inferred_content_type = FileContentType.to_content_type(file_path.suffix)\n        if inferred_content_type != content_type:\n            raise TrestleError(f'Mismatch between stated content type {content_type.name} and file path {file_path}')\n\n        self._file_path = file_path\n\n        # initialize super without writer for now\n        # Note, execute and rollback sets the writer as appropriate\n        super().__init__(None, element, content_type)\n\n    def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n        if not self._file_path.exists():\n            raise TrestleError(f'File at {self._file_path} does not exist')\n\n        with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n            if self._lastStreamPos < 0:\n                self._lastStreamPos = writer.tell()\n            else:\n                writer.seek(self._lastStreamPos)\n\n            self._writer = writer\n            super().execute()\n\n    def rollback(self) -> None:\n\"\"\"Execute the rollback action.\"\"\"\n        if not self._file_path.exists():\n            raise TrestleError(f'File at {self._file_path} does not exist')\n\n        with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n            self._writer = writer\n            super().rollback()\n\n    def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n        return f'{self._type} {self._element} to \"{self._file_path}\"'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.__init__","title":"__init__(self, file_path, element, content_type) special","text":"

                                                                            Initialize a write file action.

                                                                            It opens the file in append mode. Therefore the file needs to exist even if it is a new file.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def __init__(self, file_path: pathlib.Path, element: Element, content_type: FileContentType) -> None:\n\"\"\"Initialize a write file action.\n\n    It opens the file in append mode. Therefore the file needs to exist even if it is a new file.\n    \"\"\"\n    if not isinstance(file_path, pathlib.Path):\n        raise TrestleError('file_path should be of type pathlib.Path')\n\n    inferred_content_type = FileContentType.to_content_type(file_path.suffix)\n    if inferred_content_type != content_type:\n        raise TrestleError(f'Mismatch between stated content type {content_type.name} and file path {file_path}')\n\n    self._file_path = file_path\n\n    # initialize super without writer for now\n    # Note, execute and rollback sets the writer as appropriate\n    super().__init__(None, element, content_type)\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.__str__","title":"__str__(self) special","text":"Source code in trestle/core/models/actions.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation.\"\"\"\n    return f'{self._type} {self._element} to \"{self._file_path}\"'\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.execute","title":"execute(self)","text":"

                                                                            Execute the action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def execute(self) -> None:\n\"\"\"Execute the action.\"\"\"\n    if not self._file_path.exists():\n        raise TrestleError(f'File at {self._file_path} does not exist')\n\n    with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n        if self._lastStreamPos < 0:\n            self._lastStreamPos = writer.tell()\n        else:\n            writer.seek(self._lastStreamPos)\n\n        self._writer = writer\n        super().execute()\n
                                                                            "},{"location":"api_reference/trestle.core.models.actions/#trestle.core.models.actions.WriteFileAction.rollback","title":"rollback(self)","text":"

                                                                            Execute the rollback action.

                                                                            Source code in trestle/core/models/actions.py
                                                                            def rollback(self) -> None:\n\"\"\"Execute the rollback action.\"\"\"\n    if not self._file_path.exists():\n        raise TrestleError(f'File at {self._file_path} does not exist')\n\n    with open(self._file_path, 'a+', encoding=const.FILE_ENCODING) as writer:\n        self._writer = writer\n        super().rollback()\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/","title":"elements","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements","title":"trestle.core.models.elements","text":"

                                                                            Element wrapper of an OSCAL model element.

                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element","title":" Element ","text":"

                                                                            Element wrapper of an OSCAL model.

                                                                            Source code in trestle/core/models/elements.py
                                                                            class Element:\n\"\"\"Element wrapper of an OSCAL model.\"\"\"\n\n    IGNORE_WRAPPER_ALIAS = '__'\n\n    _allowed_sub_element_types: List[str] = ['Element', 'OscalBaseModel', 'list', 'None', 'dict']\n\n    def __init__(self, elem: OscalBaseModel, wrapper_alias: str = ''):\n\"\"\"Initialize an element wrapper.\n\n        wrapper_alias is the OSCAL alias for the given elem object and used for seriazation in to_json() method.\n\n        For example,\n         - List[Catalog.Group] element should have wrapper alias 'groups'\n         - Catalog element should have wrapper alias 'catalog'\n\n        wrapper_alias is deduced for collection type object\n\n        if wrapper_alias = IGNORE_WRAPPER_ALIAS, then it is ignored and assumed to be json-serializable during to_json()\n        \"\"\"\n        # FIXME: There are instances where elem is a list.\n        self._elem: OscalBaseModel = elem\n\n        if wrapper_alias == '' and wrapper_alias != self.IGNORE_WRAPPER_ALIAS:\n            class_name = elem.__class__.__name__\n            if utils.is_collection_field_type(elem):\n                class_name = self._get_singular_classname()\n                if class_name is None:\n                    raise TrestleError(\n                        f'wrapper_alias not found for a collection type object: {elem.__class__.__name__}'\n                    )\n            wrapper_alias = str_utils.classname_to_alias(class_name, AliasMode.JSON)\n\n        self._wrapper_alias: str = wrapper_alias\n\n    def _get_singular_classname(self) -> str:\n\"\"\"Get the inner class name for list or dict objects.\"\"\"\n        # this assumes all items in list and all values in dict are same type\n        class_name = None\n        root = getattr(self._elem, '__root__', None)\n        if root is not None:\n            type_str = root.__class__.__name__\n            if type_str == 'list':\n                class_name = self._elem.__root__[0].__class__.__name__\n            elif type_str == 'dict':\n                class_name = list(self._elem.__root__.values())[0].__class__.__name__\n        return class_name\n\n    def get(self) -> OscalBaseModel:\n\"\"\"Return the model object.\"\"\"\n        return self._elem\n\n    def _split_element_path(self, element_path: ElementPath):\n\"\"\"Split the element path into root_model and remaing attr names.\"\"\"\n        path_parts = element_path.get()\n        root_model = path_parts[0]\n        path_parts = path_parts[1:]\n\n        return root_model, path_parts\n\n    def get_at(self,\n               element_path: ElementPath = None,\n               check_parent: bool = True) -> Union[OscalBaseModel, List[OscalBaseModel]]:\n\"\"\"Get the element at the specified element path.\n\n        it will return the sub-model object at the path. Sub-model object\n        can be of type OscalBaseModel or List\n        \"\"\"\n        if element_path is None:\n            return self._elem\n\n        # find the root-model and element path parts\n        _, path_parts = self._split_element_path(element_path)\n\n        # TODO validate that self._elem is of same type as root_model\n\n        # initialize the starting element for search\n        elm = self._elem\n        if hasattr(elm, '__root__') and (isinstance(elm.__root__, dict) or isinstance(elm.__root__, list)):\n            elm = elm.__root__\n\n        # if parent exists and does not end with wildcard, use the parent as the starting element for search\n        if check_parent and element_path.get_parent(\n        ) is not None and element_path.get_parent().get_last() != ElementPath.WILDCARD:\n            elm_at = self.get_at(element_path.get_parent())\n            if elm_at is None:\n                raise TrestleNotFoundError(f'Invalid parent path {element_path.get_parent()}')\n            elm = elm_at\n\n        # return the sub-element at the specified path\n        for attr in path_parts:\n            if elm is None:\n                break\n\n            # process for wildcard and array indexes\n\n            if attr == ElementPath.WILDCARD:\n                break\n            elif attr.isnumeric():\n                if isinstance(elm, list):\n                    elm = elm[int(attr)]\n                else:\n                    # index to a non list type should return None\n                    return None\n            else:\n                elm = elm.get_field_value_by_alias(attr)\n\n        return elm\n\n    def get_preceding_element(self, element_path: ElementPath) -> Optional[OscalBaseModel]:\n\"\"\"Get the preceding element in the path.\"\"\"\n        preceding_path = element_path.get_preceding_path()\n        preceding_elm: Optional[OscalBaseModel] = self.get_at(preceding_path)\n        return preceding_elm\n\n    def _get_sub_element_obj(self, sub_element):\n\"\"\"Convert sub element into allowed model obj.\"\"\"\n        if not self.is_allowed_sub_element_type(sub_element):\n            raise TrestleError(\n                f'Sub element must be one of \"{self.get_allowed_sub_element_types()}\", found \"{sub_element.__class__}\"'\n            )\n\n        model_obj = sub_element\n        if isinstance(sub_element, Element):\n            model_obj = sub_element.get()\n\n        return model_obj\n\n    def set_at(self, element_path: ElementPath, sub_element: OscalBaseModel) -> 'Element':\n\"\"\"Set a sub_element at the path in the current element.\n\n        Sub element can be Element, OscalBaseModel, list or None type\n        It returns the element itself so that chaining operation can be done such as\n            `element.set_at(path, sub-element).get()`.\n        \"\"\"\n        # convert the element_path to ElementPath if needed\n        if isinstance(element_path, str):\n            element_path = ElementPath(element_path)\n\n        # convert sub-element to OscalBaseModel if needed\n        model_obj = self._get_sub_element_obj(sub_element)\n\n        # find the root-model and element path parts\n        _, path_parts = self._split_element_path(element_path)\n\n        # TODO validate that self._elem is of same type as root_model\n\n        # If wildcard is present, check the input type and determine the preceding element\n        if element_path.get_last() == ElementPath.WILDCARD:\n            # validate the type is either list or OscalBaseModel\n            if not isinstance(model_obj, list) and not isinstance(model_obj, OscalBaseModel):\n                raise TrestleError(\n                    f'The model object needs to be a List or OscalBaseModel for path with \"{ElementPath.WILDCARD}\"'\n                )\n\n            # since wildcard * is there, we need to go one level up for preceding element in the path\n            preceding_elm = self.get_preceding_element(element_path.get_preceding_path())\n        else:\n            # get the preceding element in the path\n            preceding_elm = self.get_preceding_element(element_path)\n\n        if preceding_elm is None:\n            raise TrestleError(f'Invalid sub element path {element_path} with no valid preceding element')\n\n        # check if it can be a valid sub_element of the parent\n        sub_element_name = element_path.get_element_name().replace('-', '_')\n        if hasattr(preceding_elm, sub_element_name) is False:\n            raise TrestleError(\n                f'Element \"{preceding_elm.__class__}\" does not have the attribute \"{sub_element_name}\" '\n                f'of type \"{model_obj.__class__}\"'\n            )\n\n        # set the sub-element\n        try:\n            setattr(preceding_elm, sub_element_name, model_obj)\n        except ValidationError:\n            sub_element_class = self.get_sub_element_class(preceding_elm, sub_element_name)\n            raise TrestleError(\n                f'Validation error: {sub_element_name} is expected to be \"{sub_element_class}\", '\n                f'but found \"{model_obj.__class__}\"'\n            )\n\n        # returning self will allow to do 'chaining' of commands after set\n        return self\n\n    def to_yaml(self) -> str:\n\"\"\"Convert into YAML string.\"\"\"\n        yaml = YAML(typ='safe')\n        yaml.default_flow_style = False\n        from io import StringIO\n        string_stream = StringIO()\n        yaml.dump(yaml.load(self.to_json(pretty=False)), string_stream)\n        yaml_data = string_stream.getvalue()\n        string_stream.close()\n\n        return yaml_data\n\n    def to_json(self, pretty: bool = True) -> str:\n\"\"\"Convert into JSON string.\"\"\"\n        if self._wrapper_alias == self.IGNORE_WRAPPER_ALIAS:\n            json_data = self._elem.oscal_serialize_json(pretty=pretty, wrapped=False)\n\n        else:\n            # Note before trying to edit this\n            # This transient model allows self._elem not be an OscalBaseModel (e.g. a DICT or LIST)\n            # typing need to be clarified.\n            if isinstance(self._elem, OscalBaseModel):\n                json_data = self._elem.oscal_serialize_json(pretty=pretty)\n            else:\n                dynamic_passer = {}\n                dynamic_passer['TransientField'] = (self._elem.__class__, Field(self, alias=self._wrapper_alias))\n                wrapper_model = create_model('TransientModel', __base__=OscalBaseModel, **dynamic_passer)\n                wrapped_model = wrapper_model.construct(**{self._wrapper_alias: self._elem})\n                json_data = wrapped_model.oscal_serialize_json(pretty=pretty, wrapped=False)\n        return json_data\n\n    @classmethod\n    def get_sub_element_class(cls, parent_elm: OscalBaseModel, sub_element_name: str):\n\"\"\"Get the class of the sub-element.\"\"\"\n        sub_element_class = parent_elm.__fields__[sub_element_name].outer_type_\n        return sub_element_class\n\n    @classmethod\n    def get_allowed_sub_element_types(cls) -> List[str]:\n\"\"\"Get the list of allowed sub element types.\"\"\"\n        return cls._allowed_sub_element_types\n\n    @classmethod\n    def is_allowed_sub_element_type(cls, elm) -> bool:\n\"\"\"Check if is of allowed sub element type.\"\"\"\n        # FIXME: The following logic does not use the _allowed_sub_element_types being defined for the class\n        if (isinstance(elm, Element) or isinstance(elm, OscalBaseModel) or isinstance(elm, list)\n                or isinstance(elm, dict) or elm is None):\n            return True\n\n        return False\n\n    def __str__(self) -> str:\n\"\"\"Return string representation of element.\"\"\"\n        return type(self._elem).__name__\n\n    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two elements are equal.\"\"\"\n        if not isinstance(other, Element):\n            return False\n\n        return self.get() == other.get()\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.IGNORE_WRAPPER_ALIAS","title":"IGNORE_WRAPPER_ALIAS","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.__eq__","title":"__eq__(self, other) special","text":"

                                                                            Check that two elements are equal.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def __eq__(self, other: object) -> bool:\n\"\"\"Check that two elements are equal.\"\"\"\n    if not isinstance(other, Element):\n        return False\n\n    return self.get() == other.get()\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.__init__","title":"__init__(self, elem, wrapper_alias='') special","text":"

                                                                            Initialize an element wrapper.

                                                                            wrapper_alias is the OSCAL alias for the given elem object and used for seriazation in to_json() method.

                                                                            For example, - List[Catalog.Group] element should have wrapper alias 'groups' - Catalog element should have wrapper alias 'catalog'

                                                                            wrapper_alias is deduced for collection type object

                                                                            if wrapper_alias = IGNORE_WRAPPER_ALIAS, then it is ignored and assumed to be json-serializable during to_json()

                                                                            Source code in trestle/core/models/elements.py
                                                                            def __init__(self, elem: OscalBaseModel, wrapper_alias: str = ''):\n\"\"\"Initialize an element wrapper.\n\n    wrapper_alias is the OSCAL alias for the given elem object and used for seriazation in to_json() method.\n\n    For example,\n     - List[Catalog.Group] element should have wrapper alias 'groups'\n     - Catalog element should have wrapper alias 'catalog'\n\n    wrapper_alias is deduced for collection type object\n\n    if wrapper_alias = IGNORE_WRAPPER_ALIAS, then it is ignored and assumed to be json-serializable during to_json()\n    \"\"\"\n    # FIXME: There are instances where elem is a list.\n    self._elem: OscalBaseModel = elem\n\n    if wrapper_alias == '' and wrapper_alias != self.IGNORE_WRAPPER_ALIAS:\n        class_name = elem.__class__.__name__\n        if utils.is_collection_field_type(elem):\n            class_name = self._get_singular_classname()\n            if class_name is None:\n                raise TrestleError(\n                    f'wrapper_alias not found for a collection type object: {elem.__class__.__name__}'\n                )\n        wrapper_alias = str_utils.classname_to_alias(class_name, AliasMode.JSON)\n\n    self._wrapper_alias: str = wrapper_alias\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.__str__","title":"__str__(self) special","text":"

                                                                            Return string representation of element.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation of element.\"\"\"\n    return type(self._elem).__name__\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get","title":"get(self)","text":"

                                                                            Return the model object.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get(self) -> OscalBaseModel:\n\"\"\"Return the model object.\"\"\"\n    return self._elem\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_allowed_sub_element_types","title":"get_allowed_sub_element_types() classmethod","text":"

                                                                            Get the list of allowed sub element types.

                                                                            Source code in trestle/core/models/elements.py
                                                                            @classmethod\ndef get_allowed_sub_element_types(cls) -> List[str]:\n\"\"\"Get the list of allowed sub element types.\"\"\"\n    return cls._allowed_sub_element_types\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_at","title":"get_at(self, element_path=None, check_parent=True)","text":"

                                                                            Get the element at the specified element path.

                                                                            it will return the sub-model object at the path. Sub-model object can be of type OscalBaseModel or List

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_at(self,\n           element_path: ElementPath = None,\n           check_parent: bool = True) -> Union[OscalBaseModel, List[OscalBaseModel]]:\n\"\"\"Get the element at the specified element path.\n\n    it will return the sub-model object at the path. Sub-model object\n    can be of type OscalBaseModel or List\n    \"\"\"\n    if element_path is None:\n        return self._elem\n\n    # find the root-model and element path parts\n    _, path_parts = self._split_element_path(element_path)\n\n    # TODO validate that self._elem is of same type as root_model\n\n    # initialize the starting element for search\n    elm = self._elem\n    if hasattr(elm, '__root__') and (isinstance(elm.__root__, dict) or isinstance(elm.__root__, list)):\n        elm = elm.__root__\n\n    # if parent exists and does not end with wildcard, use the parent as the starting element for search\n    if check_parent and element_path.get_parent(\n    ) is not None and element_path.get_parent().get_last() != ElementPath.WILDCARD:\n        elm_at = self.get_at(element_path.get_parent())\n        if elm_at is None:\n            raise TrestleNotFoundError(f'Invalid parent path {element_path.get_parent()}')\n        elm = elm_at\n\n    # return the sub-element at the specified path\n    for attr in path_parts:\n        if elm is None:\n            break\n\n        # process for wildcard and array indexes\n\n        if attr == ElementPath.WILDCARD:\n            break\n        elif attr.isnumeric():\n            if isinstance(elm, list):\n                elm = elm[int(attr)]\n            else:\n                # index to a non list type should return None\n                return None\n        else:\n            elm = elm.get_field_value_by_alias(attr)\n\n    return elm\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_preceding_element","title":"get_preceding_element(self, element_path)","text":"

                                                                            Get the preceding element in the path.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_preceding_element(self, element_path: ElementPath) -> Optional[OscalBaseModel]:\n\"\"\"Get the preceding element in the path.\"\"\"\n    preceding_path = element_path.get_preceding_path()\n    preceding_elm: Optional[OscalBaseModel] = self.get_at(preceding_path)\n    return preceding_elm\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.get_sub_element_class","title":"get_sub_element_class(parent_elm, sub_element_name) classmethod","text":"

                                                                            Get the class of the sub-element.

                                                                            Source code in trestle/core/models/elements.py
                                                                            @classmethod\ndef get_sub_element_class(cls, parent_elm: OscalBaseModel, sub_element_name: str):\n\"\"\"Get the class of the sub-element.\"\"\"\n    sub_element_class = parent_elm.__fields__[sub_element_name].outer_type_\n    return sub_element_class\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.is_allowed_sub_element_type","title":"is_allowed_sub_element_type(elm) classmethod","text":"

                                                                            Check if is of allowed sub element type.

                                                                            Source code in trestle/core/models/elements.py
                                                                            @classmethod\ndef is_allowed_sub_element_type(cls, elm) -> bool:\n\"\"\"Check if is of allowed sub element type.\"\"\"\n    # FIXME: The following logic does not use the _allowed_sub_element_types being defined for the class\n    if (isinstance(elm, Element) or isinstance(elm, OscalBaseModel) or isinstance(elm, list)\n            or isinstance(elm, dict) or elm is None):\n        return True\n\n    return False\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.set_at","title":"set_at(self, element_path, sub_element)","text":"

                                                                            Set a sub_element at the path in the current element.

                                                                            Sub element can be Element, OscalBaseModel, list or None type It returns the element itself so that chaining operation can be done such as element.set_at(path, sub-element).get().

                                                                            Source code in trestle/core/models/elements.py
                                                                            def set_at(self, element_path: ElementPath, sub_element: OscalBaseModel) -> 'Element':\n\"\"\"Set a sub_element at the path in the current element.\n\n    Sub element can be Element, OscalBaseModel, list or None type\n    It returns the element itself so that chaining operation can be done such as\n        `element.set_at(path, sub-element).get()`.\n    \"\"\"\n    # convert the element_path to ElementPath if needed\n    if isinstance(element_path, str):\n        element_path = ElementPath(element_path)\n\n    # convert sub-element to OscalBaseModel if needed\n    model_obj = self._get_sub_element_obj(sub_element)\n\n    # find the root-model and element path parts\n    _, path_parts = self._split_element_path(element_path)\n\n    # TODO validate that self._elem is of same type as root_model\n\n    # If wildcard is present, check the input type and determine the preceding element\n    if element_path.get_last() == ElementPath.WILDCARD:\n        # validate the type is either list or OscalBaseModel\n        if not isinstance(model_obj, list) and not isinstance(model_obj, OscalBaseModel):\n            raise TrestleError(\n                f'The model object needs to be a List or OscalBaseModel for path with \"{ElementPath.WILDCARD}\"'\n            )\n\n        # since wildcard * is there, we need to go one level up for preceding element in the path\n        preceding_elm = self.get_preceding_element(element_path.get_preceding_path())\n    else:\n        # get the preceding element in the path\n        preceding_elm = self.get_preceding_element(element_path)\n\n    if preceding_elm is None:\n        raise TrestleError(f'Invalid sub element path {element_path} with no valid preceding element')\n\n    # check if it can be a valid sub_element of the parent\n    sub_element_name = element_path.get_element_name().replace('-', '_')\n    if hasattr(preceding_elm, sub_element_name) is False:\n        raise TrestleError(\n            f'Element \"{preceding_elm.__class__}\" does not have the attribute \"{sub_element_name}\" '\n            f'of type \"{model_obj.__class__}\"'\n        )\n\n    # set the sub-element\n    try:\n        setattr(preceding_elm, sub_element_name, model_obj)\n    except ValidationError:\n        sub_element_class = self.get_sub_element_class(preceding_elm, sub_element_name)\n        raise TrestleError(\n            f'Validation error: {sub_element_name} is expected to be \"{sub_element_class}\", '\n            f'but found \"{model_obj.__class__}\"'\n        )\n\n    # returning self will allow to do 'chaining' of commands after set\n    return self\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.to_json","title":"to_json(self, pretty=True)","text":"

                                                                            Convert into JSON string.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def to_json(self, pretty: bool = True) -> str:\n\"\"\"Convert into JSON string.\"\"\"\n    if self._wrapper_alias == self.IGNORE_WRAPPER_ALIAS:\n        json_data = self._elem.oscal_serialize_json(pretty=pretty, wrapped=False)\n\n    else:\n        # Note before trying to edit this\n        # This transient model allows self._elem not be an OscalBaseModel (e.g. a DICT or LIST)\n        # typing need to be clarified.\n        if isinstance(self._elem, OscalBaseModel):\n            json_data = self._elem.oscal_serialize_json(pretty=pretty)\n        else:\n            dynamic_passer = {}\n            dynamic_passer['TransientField'] = (self._elem.__class__, Field(self, alias=self._wrapper_alias))\n            wrapper_model = create_model('TransientModel', __base__=OscalBaseModel, **dynamic_passer)\n            wrapped_model = wrapper_model.construct(**{self._wrapper_alias: self._elem})\n            json_data = wrapped_model.oscal_serialize_json(pretty=pretty, wrapped=False)\n    return json_data\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.Element.to_yaml","title":"to_yaml(self)","text":"

                                                                            Convert into YAML string.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def to_yaml(self) -> str:\n\"\"\"Convert into YAML string.\"\"\"\n    yaml = YAML(typ='safe')\n    yaml.default_flow_style = False\n    from io import StringIO\n    string_stream = StringIO()\n    yaml.dump(yaml.load(self.to_json(pretty=False)), string_stream)\n    yaml_data = string_stream.getvalue()\n    string_stream.close()\n\n    return yaml_data\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath","title":" ElementPath ","text":"

                                                                            Element path wrapper of an element.

                                                                            This only allows a single wildcard '*' at the end to denote elements of an array or dict

                                                                            Source code in trestle/core/models/elements.py
                                                                            class ElementPath:\n\"\"\"Element path wrapper of an element.\n\n    This only allows a single wildcard '*' at the end to denote elements of an array or dict\n    \"\"\"\n\n    PATH_SEPARATOR: str = const.ALIAS_PATH_SEPARATOR\n\n    WILDCARD: str = '*'\n\n    def __init__(self, element_path: str, parent_path: Optional['ElementPath'] = None) -> None:\n\"\"\"Initialize an element wrapper.\n\n        It assumes the element path contains oscal field alias with hyphens only\n        \"\"\"\n        self._parent_path = parent_path\n\n        self._path: List[str] = self._parse(element_path)\n\n        # Initialize private variables for lazy processing and caching\n        self._element_name: Optional[str] = None\n        self._preceding_path: Optional['ElementPath'] = None\n\n    def _parse(self, element_path: str) -> List[str]:\n\"\"\"Parse the element path and validate.\"\"\"\n        parts: List[str] = element_path.split(self.PATH_SEPARATOR)\n\n        for part in parts:\n            if part == '':\n                raise TrestleError(\n                    f'Invalid path \"{element_path}\" because there are empty path parts between \"{self.PATH_SEPARATOR}\" '\n                    'or in the beginning'\n                )\n\n        if parts[0] == self.WILDCARD:\n            raise TrestleError(f'Invalid path {element_path} with wildcard.')\n        return parts\n\n    def get(self) -> List[str]:\n\"\"\"Return the path parts as a list.\"\"\"\n        return self._path\n\n    def get_type(self, root_model: Optional[Type[Any]] = None, use_parent: bool = False) -> Type[Any]:\n\"\"\"Get the type of an element.\n\n        If possible the model type will be derived from one of the top level models,\n        otherwise a 'root model' can be passed for situations where this is not possible.\n\n        This type path should *NOT* have wild cards in it. It *may* have* indices.\n        Valid Examples:\n            catalog.metadata\n            catalog.groups\n            catalog.groups.group\n            catalog\n            catalog.groups.0\n\n        Args:\n            root_model: An OscalBaseModel Type from which to base the approach on.\n            use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n        Returns:\n            The type of the model whether or not it is an OscalBaseModel or not.\n        \"\"\"\n        effective_path: List[str]\n        if use_parent:\n            effective_path = self.get_full_path_parts()\n        else:\n            effective_path = self._path\n\n        if not root_model:\n            # lookup root model from top level oscal models or fail\n            prev_model = self._top_level_type_lookup(effective_path[0])\n        else:\n            prev_model = root_model\n        if len(effective_path) == 1:\n            return prev_model\n        # variables\n        # for current_element_str in effective_path[1:]:\n        for current_element_str in effective_path[1:]:\n            # Determine if the parent model is a collection.\n            if utils.is_collection_field_type(prev_model):\n                inner_model = utils.get_inner_type(prev_model)\n                inner_class_name = classname_to_alias(inner_model.__name__, AliasMode.JSON)\n                # Assert that the current name fits an expected form.\n                # Valid choices here are *, integer (for arrays) and the inner model alias\n                if (inner_class_name == current_element_str or current_element_str == self.WILDCARD\n                        or current_element_str.isnumeric()):\n                    prev_model = inner_model\n\n                else:\n                    raise TrestleError('Unexpected key in element path when finding type.')\n\n            else:\n                # Indices, * are not allowed on non-collection types\n                if current_element_str == self.WILDCARD:\n                    raise TrestleError(\n                        'Wild card in unexpected position when trying to find class type.'\n                        + ' Element path type lookup can only occur where a single type can be identified.'\n                    )\n                prev_model = prev_model.alias_to_field_map()[current_element_str].outer_type_\n        return prev_model\n\n    def get_obm_wrapped_type(self,\n                             root_model: Optional[Type[Any]] = None,\n                             use_parent: bool = False) -> Type[OscalBaseModel]:\n\"\"\"Get the type of the element. Wraps the collection type in an OscalBaseModel as a __root__ element.\n\n        This should principally be used for validating content.\n\n        Args:\n            root_model: An OscalBaseModel Type from which to base the approach on.\n            use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n        Returns:\n            The type of the model whether wrapped or not as an OscalBaseModel.\n        \"\"\"\n        base_type = self.get_type(root_model, use_parent)\n        # Get an outer model type.\n        origin_type = utils.get_origin(base_type)\n\n        if origin_type in [list, dict]:\n            # OSCAL does not support collections of collections directly. We should not hit this scenario\n            collection_name = self.get_last()\n            if collection_name == self.WILDCARD:\n                logger.critical('Unexpected error in type system when inferring type from element path.')\n                logger.critical('Please report this issue.')\n                raise TrestleError('Unknown error inferring type from element path.')\n            # Final path must be the alias\n\n            new_base_type = create_model(\n                str_utils.alias_to_classname(collection_name, AliasMode.JSON),\n                __base__=OscalBaseModel,\n                __root__=(base_type, ...)\n            )\n            return new_base_type\n        return base_type\n\n    def _top_level_type_lookup(self, element_str: str) -> Type[common_types.TopLevelOscalModel]:\n\"\"\"From an individual element tag, induce the type of the model.\n\n        Args:\n            element_str: individual element as text such as 'catalog' or 'profile'\n\n        Returns:\n            Top level object model such as catalog, profile etc.\n        \"\"\"\n        # Even though awkward use chain of models.\n        if element_str not in const.MODEL_TYPE_LIST:\n            raise TrestleError(f'{element_str} is not a top level model (e.g. catalog, profile)')\n        model_package = const.MODEL_TYPE_TO_MODEL_MODULE[element_str]\n        object_type, _ = ModelUtils.get_root_model(model_package)\n        object_type = cast(Type[common_types.TopLevelOscalModel], object_type)\n        return object_type\n\n    def is_multipart(self) -> bool:\n\"\"\"Assert whether or not an element path is multiple parts.\n\n        Originally element paths had to have multiple paths.\n        This provides a check for higher level code that still has that requirement.\n\n        Single part:\n            catalog\n            control\n            assessment-results\n\n        Multipart:\n            catalog.metadata\n            catalog.controls.control\n        \"\"\"\n        return len(self._path) > 1\n\n    def to_string(self) -> str:\n\"\"\"Return the path parts as a dot-separated string.\"\"\"\n        return self.PATH_SEPARATOR.join(self.get())\n\n    def get_parent(self) -> 'ElementPath':\n\"\"\"Return the parent path.\n\n        It can be None or a valid ElementPath\n        \"\"\"\n        return self._parent_path\n\n    def get_first(self) -> str:\n\"\"\"Return the first part of the path.\"\"\"\n        return self._path[0]\n\n    def get_last(self) -> str:\n\"\"\"Return the last part of the path.\"\"\"\n        return self._path[-1]\n\n    def get_full(self) -> str:\n\"\"\"Return the full path including parent path parts as a dot separated str.\"\"\"\n        all_parts = self.get_full_path_parts()\n        return self.PATH_SEPARATOR.join(all_parts)\n\n    def get_element_name(self) -> str:\n\"\"\"Return the element alias name from the path.\n\n        Essentailly this the last part of the element path\n        \"\"\"\n        # if it is available then return otherwise compute\n        if self._element_name is None:\n            element_name = self.get_last()\n            if element_name == self.WILDCARD:\n                element_name = self._path[-2]\n\n            self._element_name = element_name\n\n        return self._element_name\n\n    def get_full_path_parts(self) -> List[str]:\n\"\"\"Get full path parts to the element including parent path parts as a list.\"\"\"\n        path_parts = []\n        if self.get_parent() is not None:\n            parent_path_parts = self.get_parent().get_full_path_parts()\n            path_parts.extend(parent_path_parts)\n            path_parts.extend(self.get()[1:])  # don't use the first part\n        else:\n            path_parts.extend(self.get())\n\n        return path_parts\n\n    def get_preceding_path(self) -> 'ElementPath':\n\"\"\"Return the element path to the preceding element in the path.\"\"\"\n        # if it is available then return otherwise compute\n        if self._preceding_path is None:\n            path_parts = self.get_full_path_parts()\n\n            if len(path_parts) > 1:\n                prec_path_parts = path_parts[:-1]\n                self._preceding_path = ElementPath(self.PATH_SEPARATOR.join(prec_path_parts))\n\n        return self._preceding_path\n\n    def find_last_file_in_path(self, content_type: FileContentType, model_dir: pathlib.Path) -> pathlib.Path:\n\"\"\"Find the last (nearest) existing file in the element path leading to this element.\"\"\"\n        # model dir is the top level dir for this model, e.g. catalogs/mycat\n        path = model_dir\n        extension = FileContentType.to_file_extension(content_type)\n        good_model: pathlib.Path = None\n        for element in self._path:\n            if element == '*':\n                break\n            model_file = (path / element).with_suffix(extension)\n            if not model_file.exists():\n                break\n            path = path / element\n            good_model = model_file\n        return good_model\n\n    def make_absolute(self, model_dir: pathlib.Path, reference_dir: pathlib.Path):\n\"\"\"Make the parts absolute from the top model dir.\"\"\"\n        # Match the current relative element path to the model directory and reference directory\n        # If the element path is partial and doesn't connect to the top of the model,\n        # need to deduce absolute element path from the model_dir and the reference directory\n        # that corresponds to the root of the element path\n\n        # if first element is a model type it is already absolute\n        if self._path[0] not in const.MODEL_TYPE_LIST:\n            rel_path = list(reference_dir.relative_to(model_dir).parts)\n            rel_path.extend(self._path)\n            self._path = rel_path\n\n    def make_relative(self, model_relative_path: pathlib.Path) -> int:\n\"\"\"Make the parts relative to the model path.\"\"\"\n        # The element path should currently be absolute\n        # The model relative path should be relative to the top leve of the model\n        # Change the element path to be relative to the model being loaded\n        # Returns 0 on success and 1 on failur\n        rel_path_parts = model_relative_path.parts[:-1]\n        n_rel_parts = len(rel_path_parts)\n        # the element path can't start above the model path\n        if n_rel_parts >= len(self._path):\n            return 1\n        # confirm the leading parts match\n        for ii in range(n_rel_parts):\n            if rel_path_parts[ii] != self._path[ii]:\n                return 1\n        # chop off the leading parts of the absolute element path\n        self._path = self._path[n_rel_parts:]\n        return 0\n\n    def to_file_path(self, content_type: FileContentType = None, root_dir: str = '') -> pathlib.Path:\n\"\"\"Convert to a file or directory path for the element path.\n\n        if content_type is not passed, it will return a path for directory\n        \"\"\"\n        path_parts = self.get()\n\n        # skip wildcard\n        if path_parts[-1] == ElementPath.WILDCARD:\n            path_parts = path_parts[:-1]\n\n        if root_dir != '':\n            path_parts[0] = root_dir\n\n        path_str = '/'.join(path_parts)\n\n        # add file extension if required\n        # this will be omitted if it is a dir path\n        if content_type is not None:\n            file_extension = FileContentType.to_file_extension(content_type)\n            path_str = path_str + file_extension\n\n        # prepare the path\n        file_path: pathlib.Path = pathlib.Path(f'./{path_str}')\n\n        return file_path\n\n    def to_root_path(self, content_type: FileContentType = None) -> pathlib.Path:\n\"\"\"Convert to a file path for the element root.\"\"\"\n        path_str = f'./{self.get_first()}'\n        if content_type is not None:\n            file_extension = FileContentType.to_file_extension(content_type)\n            path_str = path_str + file_extension\n\n        file_path: pathlib.Path = pathlib.Path(path_str)\n        return file_path\n\n    def __str__(self) -> str:\n\"\"\"Return string representation of element path.\"\"\"\n        return self.to_string()\n\n    def __eq__(self, other) -> bool:\n\"\"\"Override equality method.\"\"\"\n        if not isinstance(other, ElementPath):\n            return False\n\n        return self.get() == other.get()\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.PATH_SEPARATOR","title":"PATH_SEPARATOR: str","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.WILDCARD","title":"WILDCARD: str","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.__eq__","title":"__eq__(self, other) special","text":"

                                                                            Override equality method.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def __eq__(self, other) -> bool:\n\"\"\"Override equality method.\"\"\"\n    if not isinstance(other, ElementPath):\n        return False\n\n    return self.get() == other.get()\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.__init__","title":"__init__(self, element_path, parent_path=None) special","text":"

                                                                            Initialize an element wrapper.

                                                                            It assumes the element path contains oscal field alias with hyphens only

                                                                            Source code in trestle/core/models/elements.py
                                                                            def __init__(self, element_path: str, parent_path: Optional['ElementPath'] = None) -> None:\n\"\"\"Initialize an element wrapper.\n\n    It assumes the element path contains oscal field alias with hyphens only\n    \"\"\"\n    self._parent_path = parent_path\n\n    self._path: List[str] = self._parse(element_path)\n\n    # Initialize private variables for lazy processing and caching\n    self._element_name: Optional[str] = None\n    self._preceding_path: Optional['ElementPath'] = None\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.__str__","title":"__str__(self) special","text":"

                                                                            Return string representation of element path.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def __str__(self) -> str:\n\"\"\"Return string representation of element path.\"\"\"\n    return self.to_string()\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.find_last_file_in_path","title":"find_last_file_in_path(self, content_type, model_dir)","text":"

                                                                            Find the last (nearest) existing file in the element path leading to this element.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def find_last_file_in_path(self, content_type: FileContentType, model_dir: pathlib.Path) -> pathlib.Path:\n\"\"\"Find the last (nearest) existing file in the element path leading to this element.\"\"\"\n    # model dir is the top level dir for this model, e.g. catalogs/mycat\n    path = model_dir\n    extension = FileContentType.to_file_extension(content_type)\n    good_model: pathlib.Path = None\n    for element in self._path:\n        if element == '*':\n            break\n        model_file = (path / element).with_suffix(extension)\n        if not model_file.exists():\n            break\n        path = path / element\n        good_model = model_file\n    return good_model\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get","title":"get(self)","text":"

                                                                            Return the path parts as a list.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get(self) -> List[str]:\n\"\"\"Return the path parts as a list.\"\"\"\n    return self._path\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_element_name","title":"get_element_name(self)","text":"

                                                                            Return the element alias name from the path.

                                                                            Essentailly this the last part of the element path

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_element_name(self) -> str:\n\"\"\"Return the element alias name from the path.\n\n    Essentailly this the last part of the element path\n    \"\"\"\n    # if it is available then return otherwise compute\n    if self._element_name is None:\n        element_name = self.get_last()\n        if element_name == self.WILDCARD:\n            element_name = self._path[-2]\n\n        self._element_name = element_name\n\n    return self._element_name\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_first","title":"get_first(self)","text":"

                                                                            Return the first part of the path.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_first(self) -> str:\n\"\"\"Return the first part of the path.\"\"\"\n    return self._path[0]\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_full","title":"get_full(self)","text":"

                                                                            Return the full path including parent path parts as a dot separated str.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_full(self) -> str:\n\"\"\"Return the full path including parent path parts as a dot separated str.\"\"\"\n    all_parts = self.get_full_path_parts()\n    return self.PATH_SEPARATOR.join(all_parts)\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_full_path_parts","title":"get_full_path_parts(self)","text":"

                                                                            Get full path parts to the element including parent path parts as a list.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_full_path_parts(self) -> List[str]:\n\"\"\"Get full path parts to the element including parent path parts as a list.\"\"\"\n    path_parts = []\n    if self.get_parent() is not None:\n        parent_path_parts = self.get_parent().get_full_path_parts()\n        path_parts.extend(parent_path_parts)\n        path_parts.extend(self.get()[1:])  # don't use the first part\n    else:\n        path_parts.extend(self.get())\n\n    return path_parts\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_last","title":"get_last(self)","text":"

                                                                            Return the last part of the path.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_last(self) -> str:\n\"\"\"Return the last part of the path.\"\"\"\n    return self._path[-1]\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_obm_wrapped_type","title":"get_obm_wrapped_type(self, root_model=None, use_parent=False)","text":"

                                                                            Get the type of the element. Wraps the collection type in an OscalBaseModel as a root element.

                                                                            This should principally be used for validating content.

                                                                            Parameters:

                                                                            Name Type Description Default root_model Optional[Type[Any]]

                                                                            An OscalBaseModel Type from which to base the approach on.

                                                                            None use_parent bool

                                                                            Whether or not to normalise the full path across parent ElementPaths, default to not.

                                                                            False

                                                                            Returns:

                                                                            Type Description Type[trestle.core.base_model.OscalBaseModel]

                                                                            The type of the model whether wrapped or not as an OscalBaseModel.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_obm_wrapped_type(self,\n                         root_model: Optional[Type[Any]] = None,\n                         use_parent: bool = False) -> Type[OscalBaseModel]:\n\"\"\"Get the type of the element. Wraps the collection type in an OscalBaseModel as a __root__ element.\n\n    This should principally be used for validating content.\n\n    Args:\n        root_model: An OscalBaseModel Type from which to base the approach on.\n        use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n    Returns:\n        The type of the model whether wrapped or not as an OscalBaseModel.\n    \"\"\"\n    base_type = self.get_type(root_model, use_parent)\n    # Get an outer model type.\n    origin_type = utils.get_origin(base_type)\n\n    if origin_type in [list, dict]:\n        # OSCAL does not support collections of collections directly. We should not hit this scenario\n        collection_name = self.get_last()\n        if collection_name == self.WILDCARD:\n            logger.critical('Unexpected error in type system when inferring type from element path.')\n            logger.critical('Please report this issue.')\n            raise TrestleError('Unknown error inferring type from element path.')\n        # Final path must be the alias\n\n        new_base_type = create_model(\n            str_utils.alias_to_classname(collection_name, AliasMode.JSON),\n            __base__=OscalBaseModel,\n            __root__=(base_type, ...)\n        )\n        return new_base_type\n    return base_type\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_parent","title":"get_parent(self)","text":"

                                                                            Return the parent path.

                                                                            It can be None or a valid ElementPath

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_parent(self) -> 'ElementPath':\n\"\"\"Return the parent path.\n\n    It can be None or a valid ElementPath\n    \"\"\"\n    return self._parent_path\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_preceding_path","title":"get_preceding_path(self)","text":"

                                                                            Return the element path to the preceding element in the path.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_preceding_path(self) -> 'ElementPath':\n\"\"\"Return the element path to the preceding element in the path.\"\"\"\n    # if it is available then return otherwise compute\n    if self._preceding_path is None:\n        path_parts = self.get_full_path_parts()\n\n        if len(path_parts) > 1:\n            prec_path_parts = path_parts[:-1]\n            self._preceding_path = ElementPath(self.PATH_SEPARATOR.join(prec_path_parts))\n\n    return self._preceding_path\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.get_type","title":"get_type(self, root_model=None, use_parent=False)","text":"

                                                                            Get the type of an element.

                                                                            If possible the model type will be derived from one of the top level models, otherwise a 'root model' can be passed for situations where this is not possible.

                                                                            This type path should NOT have wild cards in it. It may have* indices. Valid Examples: catalog.metadata catalog.groups catalog.groups.group catalog catalog.groups.0

                                                                            Parameters:

                                                                            Name Type Description Default root_model Optional[Type[Any]]

                                                                            An OscalBaseModel Type from which to base the approach on.

                                                                            None use_parent bool

                                                                            Whether or not to normalise the full path across parent ElementPaths, default to not.

                                                                            False

                                                                            Returns:

                                                                            Type Description Type[Any]

                                                                            The type of the model whether or not it is an OscalBaseModel or not.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def get_type(self, root_model: Optional[Type[Any]] = None, use_parent: bool = False) -> Type[Any]:\n\"\"\"Get the type of an element.\n\n    If possible the model type will be derived from one of the top level models,\n    otherwise a 'root model' can be passed for situations where this is not possible.\n\n    This type path should *NOT* have wild cards in it. It *may* have* indices.\n    Valid Examples:\n        catalog.metadata\n        catalog.groups\n        catalog.groups.group\n        catalog\n        catalog.groups.0\n\n    Args:\n        root_model: An OscalBaseModel Type from which to base the approach on.\n        use_parent: Whether or not to normalise the full path across parent ElementPaths, default to not.\n\n    Returns:\n        The type of the model whether or not it is an OscalBaseModel or not.\n    \"\"\"\n    effective_path: List[str]\n    if use_parent:\n        effective_path = self.get_full_path_parts()\n    else:\n        effective_path = self._path\n\n    if not root_model:\n        # lookup root model from top level oscal models or fail\n        prev_model = self._top_level_type_lookup(effective_path[0])\n    else:\n        prev_model = root_model\n    if len(effective_path) == 1:\n        return prev_model\n    # variables\n    # for current_element_str in effective_path[1:]:\n    for current_element_str in effective_path[1:]:\n        # Determine if the parent model is a collection.\n        if utils.is_collection_field_type(prev_model):\n            inner_model = utils.get_inner_type(prev_model)\n            inner_class_name = classname_to_alias(inner_model.__name__, AliasMode.JSON)\n            # Assert that the current name fits an expected form.\n            # Valid choices here are *, integer (for arrays) and the inner model alias\n            if (inner_class_name == current_element_str or current_element_str == self.WILDCARD\n                    or current_element_str.isnumeric()):\n                prev_model = inner_model\n\n            else:\n                raise TrestleError('Unexpected key in element path when finding type.')\n\n        else:\n            # Indices, * are not allowed on non-collection types\n            if current_element_str == self.WILDCARD:\n                raise TrestleError(\n                    'Wild card in unexpected position when trying to find class type.'\n                    + ' Element path type lookup can only occur where a single type can be identified.'\n                )\n            prev_model = prev_model.alias_to_field_map()[current_element_str].outer_type_\n    return prev_model\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.is_multipart","title":"is_multipart(self)","text":"

                                                                            Assert whether or not an element path is multiple parts.

                                                                            Originally element paths had to have multiple paths. This provides a check for higher level code that still has that requirement.

                                                                            Single part: catalog control assessment-results

                                                                            Multipart

                                                                            catalog.metadata catalog.controls.control

                                                                            Source code in trestle/core/models/elements.py
                                                                            def is_multipart(self) -> bool:\n\"\"\"Assert whether or not an element path is multiple parts.\n\n    Originally element paths had to have multiple paths.\n    This provides a check for higher level code that still has that requirement.\n\n    Single part:\n        catalog\n        control\n        assessment-results\n\n    Multipart:\n        catalog.metadata\n        catalog.controls.control\n    \"\"\"\n    return len(self._path) > 1\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.make_absolute","title":"make_absolute(self, model_dir, reference_dir)","text":"

                                                                            Make the parts absolute from the top model dir.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def make_absolute(self, model_dir: pathlib.Path, reference_dir: pathlib.Path):\n\"\"\"Make the parts absolute from the top model dir.\"\"\"\n    # Match the current relative element path to the model directory and reference directory\n    # If the element path is partial and doesn't connect to the top of the model,\n    # need to deduce absolute element path from the model_dir and the reference directory\n    # that corresponds to the root of the element path\n\n    # if first element is a model type it is already absolute\n    if self._path[0] not in const.MODEL_TYPE_LIST:\n        rel_path = list(reference_dir.relative_to(model_dir).parts)\n        rel_path.extend(self._path)\n        self._path = rel_path\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.make_relative","title":"make_relative(self, model_relative_path)","text":"

                                                                            Make the parts relative to the model path.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def make_relative(self, model_relative_path: pathlib.Path) -> int:\n\"\"\"Make the parts relative to the model path.\"\"\"\n    # The element path should currently be absolute\n    # The model relative path should be relative to the top leve of the model\n    # Change the element path to be relative to the model being loaded\n    # Returns 0 on success and 1 on failur\n    rel_path_parts = model_relative_path.parts[:-1]\n    n_rel_parts = len(rel_path_parts)\n    # the element path can't start above the model path\n    if n_rel_parts >= len(self._path):\n        return 1\n    # confirm the leading parts match\n    for ii in range(n_rel_parts):\n        if rel_path_parts[ii] != self._path[ii]:\n            return 1\n    # chop off the leading parts of the absolute element path\n    self._path = self._path[n_rel_parts:]\n    return 0\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.to_file_path","title":"to_file_path(self, content_type=None, root_dir='')","text":"

                                                                            Convert to a file or directory path for the element path.

                                                                            if content_type is not passed, it will return a path for directory

                                                                            Source code in trestle/core/models/elements.py
                                                                            def to_file_path(self, content_type: FileContentType = None, root_dir: str = '') -> pathlib.Path:\n\"\"\"Convert to a file or directory path for the element path.\n\n    if content_type is not passed, it will return a path for directory\n    \"\"\"\n    path_parts = self.get()\n\n    # skip wildcard\n    if path_parts[-1] == ElementPath.WILDCARD:\n        path_parts = path_parts[:-1]\n\n    if root_dir != '':\n        path_parts[0] = root_dir\n\n    path_str = '/'.join(path_parts)\n\n    # add file extension if required\n    # this will be omitted if it is a dir path\n    if content_type is not None:\n        file_extension = FileContentType.to_file_extension(content_type)\n        path_str = path_str + file_extension\n\n    # prepare the path\n    file_path: pathlib.Path = pathlib.Path(f'./{path_str}')\n\n    return file_path\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.to_root_path","title":"to_root_path(self, content_type=None)","text":"

                                                                            Convert to a file path for the element root.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def to_root_path(self, content_type: FileContentType = None) -> pathlib.Path:\n\"\"\"Convert to a file path for the element root.\"\"\"\n    path_str = f'./{self.get_first()}'\n    if content_type is not None:\n        file_extension = FileContentType.to_file_extension(content_type)\n        path_str = path_str + file_extension\n\n    file_path: pathlib.Path = pathlib.Path(path_str)\n    return file_path\n
                                                                            "},{"location":"api_reference/trestle.core.models.elements/#trestle.core.models.elements.ElementPath.to_string","title":"to_string(self)","text":"

                                                                            Return the path parts as a dot-separated string.

                                                                            Source code in trestle/core/models/elements.py
                                                                            def to_string(self) -> str:\n\"\"\"Return the path parts as a dot-separated string.\"\"\"\n    return self.PATH_SEPARATOR.join(self.get())\n
                                                                            "},{"location":"api_reference/trestle.core.models.file_content_type/","title":"file_content_type","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type","title":"trestle.core.models.file_content_type","text":"

                                                                            Action wrapper of a command.

                                                                            "},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType","title":" FileContentType (Enum) ","text":"

                                                                            File Content type for read/write.

                                                                            Source code in trestle/core/models/file_content_type.py
                                                                            class FileContentType(Enum):\n\"\"\"File Content type for read/write.\"\"\"\n\n    # JSON formatted content\n    JSON = 1\n\n    # YAML formatted content\n    YAML = 2\n\n    # No extension and possibly a DIR\n    DIRLIKE = 3\n\n    # Type could not be determined\n    UNKNOWN = 4\n\n    @classmethod\n    def to_file_extension(cls, content_type: 'FileContentType') -> str:\n\"\"\"Get file extension for the type, including the dot.\"\"\"\n        if content_type == FileContentType.YAML:\n            return '.yaml'\n        if content_type == FileContentType.JSON:\n            return '.json'\n        raise TrestleError(f'Invalid file content type {content_type}')\n\n    @classmethod\n    def to_content_type(cls, file_extension: str) -> 'FileContentType':\n\"\"\"Get content type form file extension, including the dot.\"\"\"\n        if file_extension == '.json':\n            return FileContentType.JSON\n        if file_extension == '.yaml' or file_extension == '.yml':\n            return FileContentType.YAML\n        if not file_extension:\n            return FileContentType.DIRLIKE\n\n        raise TrestleError(f'Unsupported file extension {file_extension}')\n\n    @classmethod\n    def path_to_content_type(cls, file_path: Path) -> 'FileContentType':\n\"\"\"Get content type from file path looking for extension.\"\"\"\n        if file_path.with_suffix('.json').exists():\n            return FileContentType.JSON\n        if file_path.with_suffix('.yaml').exists():\n            return FileContentType.YAML\n        if file_path.with_suffix('.yml').exists():\n            return FileContentType.YAML\n        return FileContentType.UNKNOWN\n\n    @classmethod\n    def dir_to_content_type(cls, dir_path: Path) -> 'FileContentType':\n\"\"\"Get content type by looking for json or yaml files in dir.\"\"\"\n        files = dir_path.glob('*')\n        for file in files:\n            if file.is_file():\n                suffix = file.suffix\n                if suffix == '.json':\n                    return FileContentType.JSON\n                if suffix in ['.yaml', '.yml']:\n                    return FileContentType.YAML\n        return FileContentType.UNKNOWN\n\n    @classmethod\n    def path_to_file_extension(cls, file_path: Path) -> str:\n\"\"\"Get extension from file path looking for extension.\"\"\"\n        if file_path.with_suffix('.json').exists():\n            return '.json'\n        if file_path.with_suffix('.yaml').exists():\n            return '.yaml'\n        if file_path.with_suffix('.yml').exists():\n            return '.yml'\n        return ''\n\n    @classmethod\n    def is_readable_file(cls, content_type: 'FileContentType') -> bool:\n\"\"\"Is the file a type that can be read directly.\"\"\"\n        return content_type == FileContentType.JSON or content_type == FileContentType.YAML\n
                                                                            "},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.DIRLIKE","title":"DIRLIKE","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.JSON","title":"JSON","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.UNKNOWN","title":"UNKNOWN","text":""},{"location":"api_reference/trestle.core.models.file_content_type/#trestle.core.models.file_content_type.FileContentType.YAML","title":"YAML","text":""},{"location":"api_reference/trestle.core.models.interfaces/","title":"interfaces","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces","title":"trestle.core.models.interfaces","text":"

                                                                            Interfaces for use within other trestle functions defined as pydantic data models.

                                                                            "},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly","title":" OSCALAssembly (TrestleBaseModel) pydantic-model","text":"

                                                                            Data model to represent an assembled set of OSCAL objects.

                                                                            Here the assembly represents the constraints as expected by the current OSCAL schema. At this point in time a 'flat' model has been chosen rather than an tree.

                                                                            Source code in trestle/core/models/interfaces.py
                                                                            class OSCALAssembly(TrestleBaseModel):\n\"\"\"Data model to represent an assembled set of OSCAL objects.\n\n    Here the assembly represents the constraints as expected by the current OSCAL\n    schema. At this point in time a 'flat' model has been chosen rather than an tree.\n    \"\"\"\n\n    poam: Optional[o_poam.PlanOfActionAndMilestones] = None\n    sar: Optional[o_ar.AssessmentResults] = None\n    sap: Optional[o_ap.AssessmentPlan] = None\n    ssp: Optional[o_ssp.SystemSecurityPlan] = None\n    profiles: Optional[Dict[str, o_profile.Profile]] = None\n    catalogs: Optional[Dict[str, o_catalog.Catalog]] = None\n    components: Optional[Dict[str, o_component.ComponentDefinition]] = None\n\n    class Config:\n\"\"\"Pydantic config overrides.\"\"\"\n\n        allow_population_by_field_name = True\n        # Enforce strict schema\n        extra = Extra.forbid\n        # Validate on assignment of variables to ensure no escapes\n        validate_assignment = True\n
                                                                            "},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.catalogs","title":"catalogs: Dict[str, trestle.oscal.catalog.Catalog] pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.components","title":"components: Dict[str, trestle.oscal.component.ComponentDefinition] pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.poam","title":"poam: PlanOfActionAndMilestones pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.profiles","title":"profiles: Dict[str, trestle.oscal.profile.Profile] pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.sap","title":"sap: AssessmentPlan pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.sar","title":"sar: AssessmentResults pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.ssp","title":"ssp: SystemSecurityPlan pydantic-field","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.interfaces/#trestle.core.models.interfaces.OSCALAssembly.Config","title":" Config ","text":"

                                                                            Pydantic config overrides.

                                                                            Source code in trestle/core/models/interfaces.py
                                                                            class Config:\n\"\"\"Pydantic config overrides.\"\"\"\n\n    allow_population_by_field_name = True\n    # Enforce strict schema\n    extra = Extra.forbid\n    # Validate on assignment of variables to ensure no escapes\n    validate_assignment = True\n
                                                                            allow_population_by_field_name \u00a4 extra \u00a4 validate_assignment \u00a4"},{"location":"api_reference/trestle.core.models.plans/","title":"plans","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans","title":"trestle.core.models.plans","text":"

                                                                            Plan of action of a command.

                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan","title":" Plan ","text":"

                                                                            Plan of action of a command.

                                                                            Source code in trestle/core/models/plans.py
                                                                            class Plan:\n\"\"\"Plan of action of a command.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize a plan.\"\"\"\n        self._actions: List[Action] = []\n\n    def _action_key(self, action: Action) -> int:\n        return hash(action)\n\n    def __str__(self) -> str:\n\"\"\"Print the plan.\"\"\"\n        list_actions = []\n        index = 1\n        for action in self._actions:\n            list_actions.append(f'{index}. {action}')\n            index = index + 1\n\n        list_str = '\\n'.join(list_actions)\n        return list_str\n\n    def get_actions(self) -> List[Action]:\n\"\"\"Get all actions.\"\"\"\n        return self._actions\n\n    def add_action(self, action: Action) -> None:\n\"\"\"Add a new action.\"\"\"\n        self._actions.append(action)\n\n    def add_actions(self, actions: List[Action]) -> None:\n\"\"\"Add actions in order.\"\"\"\n        self._actions.extend(actions)\n\n    def clear_actions(self) -> None:\n\"\"\"Clear all actions.\"\"\"\n        self._actions = []\n\n    def execute(self) -> None:\n\"\"\"Execute the actions in the plan.\"\"\"\n        for action in self._actions:\n            try:\n                action.execute()\n            except Exception as e:\n                logger.error(f'Failed to execute action {action} for the plan: {e}. Rolling back.')\n                self.rollback()\n                raise e\n\n    def rollback(self) -> None:\n\"\"\"Rollback the actions in the plan.\"\"\"\n        # execute in reverse order\n        for action in reversed(self._actions):\n            if action.has_rollback() is False:\n                raise UnsupportedOperation(f'{action.get_type()} does not support rollback')\n            action.rollback()\n\n    def __eq__(self, other: object) -> bool:\n\"\"\"Check that two plans are equal.\"\"\"\n        if not isinstance(other, Plan):\n            return False\n\n        return self.get_actions() == other.get_actions()\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.__eq__","title":"__eq__(self, other) special","text":"

                                                                            Check that two plans are equal.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def __eq__(self, other: object) -> bool:\n\"\"\"Check that two plans are equal.\"\"\"\n    if not isinstance(other, Plan):\n        return False\n\n    return self.get_actions() == other.get_actions()\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.__init__","title":"__init__(self) special","text":"

                                                                            Initialize a plan.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize a plan.\"\"\"\n    self._actions: List[Action] = []\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.__str__","title":"__str__(self) special","text":"

                                                                            Print the plan.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def __str__(self) -> str:\n\"\"\"Print the plan.\"\"\"\n    list_actions = []\n    index = 1\n    for action in self._actions:\n        list_actions.append(f'{index}. {action}')\n        index = index + 1\n\n    list_str = '\\n'.join(list_actions)\n    return list_str\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.add_action","title":"add_action(self, action)","text":"

                                                                            Add a new action.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def add_action(self, action: Action) -> None:\n\"\"\"Add a new action.\"\"\"\n    self._actions.append(action)\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.add_actions","title":"add_actions(self, actions)","text":"

                                                                            Add actions in order.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def add_actions(self, actions: List[Action]) -> None:\n\"\"\"Add actions in order.\"\"\"\n    self._actions.extend(actions)\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.clear_actions","title":"clear_actions(self)","text":"

                                                                            Clear all actions.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def clear_actions(self) -> None:\n\"\"\"Clear all actions.\"\"\"\n    self._actions = []\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.execute","title":"execute(self)","text":"

                                                                            Execute the actions in the plan.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def execute(self) -> None:\n\"\"\"Execute the actions in the plan.\"\"\"\n    for action in self._actions:\n        try:\n            action.execute()\n        except Exception as e:\n            logger.error(f'Failed to execute action {action} for the plan: {e}. Rolling back.')\n            self.rollback()\n            raise e\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.get_actions","title":"get_actions(self)","text":"

                                                                            Get all actions.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def get_actions(self) -> List[Action]:\n\"\"\"Get all actions.\"\"\"\n    return self._actions\n
                                                                            "},{"location":"api_reference/trestle.core.models.plans/#trestle.core.models.plans.Plan.rollback","title":"rollback(self)","text":"

                                                                            Rollback the actions in the plan.

                                                                            Source code in trestle/core/models/plans.py
                                                                            def rollback(self) -> None:\n\"\"\"Rollback the actions in the plan.\"\"\"\n    # execute in reverse order\n    for action in reversed(self._actions):\n        if action.has_rollback() is False:\n            raise UnsupportedOperation(f'{action.get_type()} does not support rollback')\n        action.rollback()\n
                                                                            "},{"location":"api_reference/trestle.core.object_factory/","title":"object_factory","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory","title":"trestle.core.object_factory","text":"

                                                                            Generic object factory.

                                                                            "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory","title":" ObjectFactory ","text":"

                                                                            Allow registration and creation of factory objects.

                                                                            Source code in trestle/core/object_factory.py
                                                                            class ObjectFactory:\n\"\"\"Allow registration and creation of factory objects.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize the objects dictionary as empty.\"\"\"\n        self._objects: Dict[str, Any] = {}\n\n    def register_object(self, mode: str, obj: Any) -> None:\n\"\"\"Register an object to the object factory.\n\n        Args:\n            mode: Descriptive key for the mode / type of object to be retrieved.\n            obj: The object type to be registered.\n        \"\"\"\n        self._objects[mode] = obj\n\n    def get(self, args: argparse.Namespace) -> Any:\n\"\"\"Create the object from the args.\"\"\"\n        return self._objects.get(args.mode)\n\n    def get_all(self) -> ValuesView[Any]:\n\"\"\"Get all registered objects.\"\"\"\n        return self._objects.values()\n
                                                                            "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.__init__","title":"__init__(self) special","text":"

                                                                            Initialize the objects dictionary as empty.

                                                                            Source code in trestle/core/object_factory.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize the objects dictionary as empty.\"\"\"\n    self._objects: Dict[str, Any] = {}\n
                                                                            "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.get","title":"get(self, args)","text":"

                                                                            Create the object from the args.

                                                                            Source code in trestle/core/object_factory.py
                                                                            def get(self, args: argparse.Namespace) -> Any:\n\"\"\"Create the object from the args.\"\"\"\n    return self._objects.get(args.mode)\n
                                                                            "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.get_all","title":"get_all(self)","text":"

                                                                            Get all registered objects.

                                                                            Source code in trestle/core/object_factory.py
                                                                            def get_all(self) -> ValuesView[Any]:\n\"\"\"Get all registered objects.\"\"\"\n    return self._objects.values()\n
                                                                            "},{"location":"api_reference/trestle.core.object_factory/#trestle.core.object_factory.ObjectFactory.register_object","title":"register_object(self, mode, obj)","text":"

                                                                            Register an object to the object factory.

                                                                            Parameters:

                                                                            Name Type Description Default mode str

                                                                            Descriptive key for the mode / type of object to be retrieved.

                                                                            required obj Any

                                                                            The object type to be registered.

                                                                            required Source code in trestle/core/object_factory.py
                                                                            def register_object(self, mode: str, obj: Any) -> None:\n\"\"\"Register an object to the object factory.\n\n    Args:\n        mode: Descriptive key for the mode / type of object to be retrieved.\n        obj: The object type to be registered.\n    \"\"\"\n    self._objects[mode] = obj\n
                                                                            "},{"location":"api_reference/trestle.core.parser/","title":"parser","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser","title":"trestle.core.parser","text":"

                                                                            Model parsing for use when models themselves must be inferred and are not known.

                                                                            Under most use cases trestle.core.base_model.OscalBaseModel provides functionality for loading Oscal models from files. However, under some circumstances the model internals are unknown. Use of this module should be avoided unless the BaseModel functionality is inadequate.

                                                                            "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.parser/#trestle.core.parser-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.parse_dict","title":"parse_dict(data, model_name)","text":"

                                                                            Load a model from the data dict.

                                                                            This functionality is provided for situations when the OSCAL data type is not known ahead of time. Here the model has been loaded into memory using json loads or similar and passed as a dict.

                                                                            Parameters:

                                                                            Name Type Description Default data Dict[str, Any]

                                                                            Oscal data loaded into memory as a dictionary with the root key removed.

                                                                            required model_name str

                                                                            should be of the form 'module.class' from trestle.oscal.* modules

                                                                            required

                                                                            Returns:

                                                                            Type Description OscalBaseModel

                                                                            The oscal model of the desired model.

                                                                            Source code in trestle/core/parser.py
                                                                            def parse_dict(data: Dict[str, Any], model_name: str) -> OscalBaseModel:\n\"\"\"Load a model from the data dict.\n\n    This functionality is provided for situations when the OSCAL data type is not known ahead of time. Here the model\n    has been loaded into memory using json loads or similar and passed as a dict.\n\n    Args:\n        data: Oscal data loaded into memory as a dictionary with the `root key` removed.\n        model_name: should be of the form 'module.class' from trestle.oscal.* modules\n\n    Returns:\n        The oscal model of the desired model.\n    \"\"\"\n    if data is None:\n        raise TrestleError('data name is required')\n\n    if model_name is None:\n        raise TrestleError('model_name is required')\n\n    parts = model_name.split('.')\n    class_name = parts.pop()\n    module_name = '.'.join(parts)\n\n    logger.debug(f'Loading class \"{class_name}\" from \"{module_name}\"')\n    module = importlib.import_module(module_name)\n    mclass: OscalBaseModel = getattr(module, class_name)\n    if mclass is None:\n        raise TrestleError(f'class \"{class_name}\" could not be found in \"{module_name}\"')\n\n    instance = mclass.parse_obj(data)\n    return instance\n
                                                                            "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.root_key","title":"root_key(data)","text":"

                                                                            Find root model name in the data.

                                                                            Source code in trestle/core/parser.py
                                                                            def root_key(data: Dict[str, Any]) -> str:\n\"\"\"Find root model name in the data.\"\"\"\n    if len(data.items()) == 1:\n        return next(iter(data))\n\n    raise TrestleError('data does not contain a root key')\n
                                                                            "},{"location":"api_reference/trestle.core.parser/#trestle.core.parser.to_full_model_name","title":"to_full_model_name(root_key)","text":"

                                                                            Find model name from the root_key in the file.

                                                                            Parameters:

                                                                            Name Type Description Default root_key str

                                                                            root key such as 'system-security-plan' from a top level OSCAL model.

                                                                            required Source code in trestle/core/parser.py
                                                                            def to_full_model_name(root_key: str) -> str:\n\"\"\"\n    Find model name from the root_key in the file.\n\n    Args:\n        root_key: root key such as 'system-security-plan' from a top level OSCAL model.\n    \"\"\"\n    if root_key not in const.MODEL_TYPE_LIST:\n        raise TrestleError(f'{root_key} is not a top level model name.')\n\n    module = const.MODEL_TYPE_TO_MODEL_MODULE[root_key]\n    class_name = alias_to_classname(root_key, AliasMode.JSON)\n    return f'{module}.{class_name}'\n
                                                                            "},{"location":"api_reference/trestle.core.pipeline/","title":"pipeline","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline","title":"trestle.core.pipeline","text":"

                                                                            Abstract base class for pipelines and filters.

                                                                            "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline","title":" Pipeline ","text":"

                                                                            Pipeline base class.

                                                                            Source code in trestle/core/pipeline.py
                                                                            class Pipeline():\n\"\"\"Pipeline base class.\"\"\"\n\n    class Filter(ABC):\n\"\"\"Filter class used by pipeline.\"\"\"\n\n        @abstractclassmethod\n        def process(self, input_: Any) -> Any:\n\"\"\"Process the input to output.\"\"\"\n            return input_\n\n    def __init__(self, filters: List[Filter]) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self._filters = filters\n\n    def process(self, input_: Any) -> Any:\n\"\"\"Process the filter pipeline.\"\"\"\n        for filter_ in self._filters:\n            input_ = filter_.process(input_)\n        return input_\n
                                                                            "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline.Filter","title":" Filter (ABC) ","text":"

                                                                            Filter class used by pipeline.

                                                                            Source code in trestle/core/pipeline.py
                                                                            class Filter(ABC):\n\"\"\"Filter class used by pipeline.\"\"\"\n\n    @abstractclassmethod\n    def process(self, input_: Any) -> Any:\n\"\"\"Process the input to output.\"\"\"\n        return input_\n
                                                                            Methods\u00a4 process(input_) classmethod \u00a4

                                                                            Process the input to output.

                                                                            Source code in trestle/core/pipeline.py
                                                                            @abstractclassmethod\ndef process(self, input_: Any) -> Any:\n\"\"\"Process the input to output.\"\"\"\n    return input_\n
                                                                            "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline.__init__","title":"__init__(self, filters) special","text":"

                                                                            Initialize the class.

                                                                            Source code in trestle/core/pipeline.py
                                                                            def __init__(self, filters: List[Filter]) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self._filters = filters\n
                                                                            "},{"location":"api_reference/trestle.core.pipeline/#trestle.core.pipeline.Pipeline.process","title":"process(self, input_)","text":"

                                                                            Process the filter pipeline.

                                                                            Source code in trestle/core/pipeline.py
                                                                            def process(self, input_: Any) -> Any:\n\"\"\"Process the filter pipeline.\"\"\"\n    for filter_ in self._filters:\n        input_ = filter_.process(input_)\n    return input_\n
                                                                            "},{"location":"api_reference/trestle.core.profile_resolver/","title":"profile_resolver","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver","title":"trestle.core.profile_resolver","text":"

                                                                            Create resolved catalog from profile.

                                                                            "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver","title":" ProfileResolver ","text":"

                                                                            Class to resolve a catalog given a profile.

                                                                            Source code in trestle/core/profile_resolver.py
                                                                            class ProfileResolver():\n\"\"\"Class to resolve a catalog given a profile.\"\"\"\n\n    @staticmethod\n    def _extract_inherited_props(res_cat: cat.Catalog) -> Tuple[cat.Catalog, Dict[str, Any]]:\n\"\"\"\n        Build the control dict of inherited props.\n\n        Args:\n            The resolved profile catalog with a possible temporary part in each control\n\n        Returns:\n            The temporary parts are removed from each control and a Dict of added props per control_id is returned\n\n        Notes:\n        If an upstream profile adds props to the control they are tracked in a special temporary part in the control\n        called const.TRESTLE_INHERITED_PROPS_TRACKER.  If that part is present in a control its contents should be added\n        to the dict entry for that control, and the part removed from the control.\n        \"\"\"\n        prop_dict: Dict[str, Any] = {}\n        cat_interface = CatalogInterface(res_cat)\n        for control in cat_interface.get_all_controls_from_dict():\n            part: com.Part = pop_item_from_list(control.parts, TRESTLE_INHERITED_PROPS_TRACKER, lambda p: p.name)\n            if part:\n                props_list: List[Dict[str, Any]] = []\n                for prop in as_list(part.props):\n                    props_list.append({'name': prop.name, 'value': prop.value})\n                for sub_part in as_list(part.parts):\n                    for prop in as_list(sub_part.props):\n                        props_list.append({'name': prop.name, 'value': prop.value, 'part_name': sub_part.title})\n                prop_dict[control.id] = props_list\n        cat_interface.update_catalog_controls()\n        clean_res_cat = cat_interface.get_catalog()\n        return clean_res_cat, prop_dict\n\n    @staticmethod\n    def get_resolved_profile_catalog_and_inherited_props(\n        trestle_root: pathlib.Path,\n        profile_path: str,\n        block_adds: bool = False,\n        block_params: bool = False,\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> Tuple[cat.Catalog, Optional[Dict[str, Any]]]:\n\"\"\"\n        Create the resolved profile catalog given a profile path along with inherited props.\n\n        Args:\n            trestle_root: root directory of the trestle workspace\n            profile_path: string path or uri of the profile being resolved\n            block_adds: prevent the application of adds in the final profile\n            block_params: prevent the application of setparams in the final profile\n            params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n            param_rep: desired way to convert params to strings\n            show_value_warnings: warn if prose references a value that has not been set\n            value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n            value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n        Returns:\n            The resolved profile catalog and a control dict of inherited props\n        \"\"\"\n        logger.debug(f'get resolved profile catalog and inherited props for {profile_path} via generated Import.')\n        import_ = prof.Import(href=str(profile_path), include_all={})\n        # The final Import has change_prose=True to force parameter substitution in the prose only at the last stage.\n        import_filter = Import(\n            trestle_root,\n            import_, [],\n            True,\n            block_adds,\n            block_params,\n            params_format,\n            param_rep,\n            None,\n            show_value_warnings,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        logger.debug('launch pipeline')\n        resolved_profile_catalog = next(import_filter.process())\n        resolved_profile_catalog, inherited_props = ProfileResolver._extract_inherited_props(resolved_profile_catalog)\n        return resolved_profile_catalog, inherited_props\n\n    @staticmethod\n    def get_resolved_profile_catalog(\n        trestle_root: pathlib.Path,\n        profile_path: str,\n        block_adds: bool = False,\n        block_params: bool = False,\n        params_format: Optional[str] = None,\n        param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> cat.Catalog:\n\"\"\"\n        Create the resolved profile catalog given a profile path.\n\n        Args:\n            trestle_root: root directory of the trestle workspace\n            profile_path: string path or uri of the profile being resolved\n            block_adds: prevent the application of adds in the final profile\n            block_params: prevent the application of setparams in the final profile\n            params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n            param_rep: desired way to convert params to strings\n            show_value_warnings: warn if prose references a value that has not been set\n            value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n            value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n        Returns:\n            The resolved profile catalog\n        \"\"\"\n        logger.debug(f'get resolved profile catalog for {profile_path} via generated Import.')\n        resolved_profile_catalog, _ = ProfileResolver.get_resolved_profile_catalog_and_inherited_props(\n            trestle_root,\n            profile_path,\n            block_adds,\n            block_params,\n            params_format,\n            param_rep,\n            show_value_warnings,\n            value_assigned_prefix,\n            value_not_assigned_prefix\n        )\n        return resolved_profile_catalog\n
                                                                            "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver.get_resolved_profile_catalog","title":"get_resolved_profile_catalog(trestle_root, profile_path, block_adds=False, block_params=False, params_format=None, param_rep=<ParameterRep.LEAVE_MOUSTACHE: 0>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                                                            Create the resolved profile catalog given a profile path.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            root directory of the trestle workspace

                                                                            required profile_path str

                                                                            string path or uri of the profile being resolved

                                                                            required block_adds bool

                                                                            prevent the application of adds in the final profile

                                                                            False block_params bool

                                                                            prevent the application of setparams in the final profile

                                                                            False params_format Optional[str]

                                                                            optional pattern with dot to wrap the param string, where dot represents the param string

                                                                            None param_rep ParameterRep

                                                                            desired way to convert params to strings

                                                                            <ParameterRep.LEAVE_MOUSTACHE: 0> show_value_warnings bool

                                                                            warn if prose references a value that has not been set

                                                                            False value_assigned_prefix Optional[str]

                                                                            Prefix placed in front of param string if a value was assigned

                                                                            None value_not_assigned_prefix Optional[str]

                                                                            Prefix placed in front of param string if a value was not assigned

                                                                            None

                                                                            Returns:

                                                                            Type Description Catalog

                                                                            The resolved profile catalog

                                                                            Source code in trestle/core/profile_resolver.py
                                                                            @staticmethod\ndef get_resolved_profile_catalog(\n    trestle_root: pathlib.Path,\n    profile_path: str,\n    block_adds: bool = False,\n    block_params: bool = False,\n    params_format: Optional[str] = None,\n    param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> cat.Catalog:\n\"\"\"\n    Create the resolved profile catalog given a profile path.\n\n    Args:\n        trestle_root: root directory of the trestle workspace\n        profile_path: string path or uri of the profile being resolved\n        block_adds: prevent the application of adds in the final profile\n        block_params: prevent the application of setparams in the final profile\n        params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n        param_rep: desired way to convert params to strings\n        show_value_warnings: warn if prose references a value that has not been set\n        value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n        value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n    Returns:\n        The resolved profile catalog\n    \"\"\"\n    logger.debug(f'get resolved profile catalog for {profile_path} via generated Import.')\n    resolved_profile_catalog, _ = ProfileResolver.get_resolved_profile_catalog_and_inherited_props(\n        trestle_root,\n        profile_path,\n        block_adds,\n        block_params,\n        params_format,\n        param_rep,\n        show_value_warnings,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    return resolved_profile_catalog\n
                                                                            "},{"location":"api_reference/trestle.core.profile_resolver/#trestle.core.profile_resolver.ProfileResolver.get_resolved_profile_catalog_and_inherited_props","title":"get_resolved_profile_catalog_and_inherited_props(trestle_root, profile_path, block_adds=False, block_params=False, params_format=None, param_rep=<ParameterRep.LEAVE_MOUSTACHE: 0>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) staticmethod","text":"

                                                                            Create the resolved profile catalog given a profile path along with inherited props.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            root directory of the trestle workspace

                                                                            required profile_path str

                                                                            string path or uri of the profile being resolved

                                                                            required block_adds bool

                                                                            prevent the application of adds in the final profile

                                                                            False block_params bool

                                                                            prevent the application of setparams in the final profile

                                                                            False params_format Optional[str]

                                                                            optional pattern with dot to wrap the param string, where dot represents the param string

                                                                            None param_rep ParameterRep

                                                                            desired way to convert params to strings

                                                                            <ParameterRep.LEAVE_MOUSTACHE: 0> show_value_warnings bool

                                                                            warn if prose references a value that has not been set

                                                                            False value_assigned_prefix Optional[str]

                                                                            Prefix placed in front of param string if a value was assigned

                                                                            None value_not_assigned_prefix Optional[str]

                                                                            Prefix placed in front of param string if a value was not assigned

                                                                            None

                                                                            Returns:

                                                                            Type Description Tuple[trestle.oscal.catalog.Catalog, Optional[Dict[str, Any]]]

                                                                            The resolved profile catalog and a control dict of inherited props

                                                                            Source code in trestle/core/profile_resolver.py
                                                                            @staticmethod\ndef get_resolved_profile_catalog_and_inherited_props(\n    trestle_root: pathlib.Path,\n    profile_path: str,\n    block_adds: bool = False,\n    block_params: bool = False,\n    params_format: Optional[str] = None,\n    param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> Tuple[cat.Catalog, Optional[Dict[str, Any]]]:\n\"\"\"\n    Create the resolved profile catalog given a profile path along with inherited props.\n\n    Args:\n        trestle_root: root directory of the trestle workspace\n        profile_path: string path or uri of the profile being resolved\n        block_adds: prevent the application of adds in the final profile\n        block_params: prevent the application of setparams in the final profile\n        params_format: optional pattern with dot to wrap the param string, where dot represents the param string\n        param_rep: desired way to convert params to strings\n        show_value_warnings: warn if prose references a value that has not been set\n        value_assigned_prefix: Prefix placed in front of param string if a value was assigned\n        value_not_assigned_prefix: Prefix placed in front of param string if a value was *not* assigned\n\n    Returns:\n        The resolved profile catalog and a control dict of inherited props\n    \"\"\"\n    logger.debug(f'get resolved profile catalog and inherited props for {profile_path} via generated Import.')\n    import_ = prof.Import(href=str(profile_path), include_all={})\n    # The final Import has change_prose=True to force parameter substitution in the prose only at the last stage.\n    import_filter = Import(\n        trestle_root,\n        import_, [],\n        True,\n        block_adds,\n        block_params,\n        params_format,\n        param_rep,\n        None,\n        show_value_warnings,\n        value_assigned_prefix,\n        value_not_assigned_prefix\n    )\n    logger.debug('launch pipeline')\n    resolved_profile_catalog = next(import_filter.process())\n    resolved_profile_catalog, inherited_props = ProfileResolver._extract_inherited_props(resolved_profile_catalog)\n    return resolved_profile_catalog, inherited_props\n
                                                                            "},{"location":"api_reference/trestle.core.refs_validator/","title":"refs_validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator","title":"trestle.core.refs_validator","text":"

                                                                            Validate by confirming all refs have corresponding id.

                                                                            "},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator.RefsValidator","title":" RefsValidator (Validator) ","text":"

                                                                            Validator to confirm all references in responsible parties are found in roles.

                                                                            Source code in trestle/core/refs_validator.py
                                                                            class RefsValidator(Validator):\n\"\"\"Validator to confirm all references in responsible parties are found in roles.\"\"\"\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            True (valid) if the model's responsible parties match those found in roles.\n        \"\"\"\n        roles = as_list(model.metadata.roles)\n        role_ids = [role.id for role in roles]\n        responsible_parties = as_list(model.metadata.responsible_parties)\n        if not responsible_parties:\n            return True\n        party_roles = [party.role_id for party in responsible_parties]\n        # return true if all party roles are in the roles list\n        return all(item in role_ids for item in party_roles)\n
                                                                            "},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator.RefsValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.refs_validator/#trestle.core.refs_validator.RefsValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                                                            Test if the model is valid.

                                                                            Parameters:

                                                                            Name Type Description Default model ~TopLevelOscalModel

                                                                            A top level OSCAL model.

                                                                            required quiet bool

                                                                            Don't report msgs unless invalid.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            True (valid) if the model's responsible parties match those found in roles.

                                                                            Source code in trestle/core/refs_validator.py
                                                                            def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        True (valid) if the model's responsible parties match those found in roles.\n    \"\"\"\n    roles = as_list(model.metadata.roles)\n    role_ids = [role.id for role in roles]\n    responsible_parties = as_list(model.metadata.responsible_parties)\n    if not responsible_parties:\n        return True\n    party_roles = [party.role_id for party in responsible_parties]\n    # return true if all party roles are in the roles list\n    return all(item in role_ids for item in party_roles)\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/","title":"cache","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache","title":"trestle.core.remote.cache","text":"

                                                                            Trestle cache operations library.

                                                                            Allows for using URI's to reference external directories and then expand.

                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase","title":" FetcherBase (ABC) ","text":"

                                                                            FetcherBase - base class for caching and fetching remote oscal objects.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            class FetcherBase(ABC):\n\"\"\"FetcherBase - base class for caching and fetching remote oscal objects.\"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Intialize fetcher base.\n\n        Args:\n            trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n            uri: Reference to the source object to cache.\n        \"\"\"\n        logger.debug('Initializing FetcherBase')\n        self._cached_object_path: pathlib.Path\n        self._uri = uri\n        self._trestle_root = trestle_root.resolve()\n        self._trestle_cache_path: pathlib.Path = self._trestle_root / const.TRESTLE_CACHE_DIR\n        # ensure trestle cache directory exists.\n        self._trestle_cache_path.mkdir(exist_ok=True)\n        self._expiration_seconds = const.DAY_SECONDS\n\n    @staticmethod\n    def _time_since_modification(file_path: pathlib.Path) -> datetime.timedelta:\n\"\"\"Get time since last modification.\"\"\"\n        last_modification = datetime.datetime.fromtimestamp(file_path.stat().st_mtime)\n        return datetime.datetime.now() - last_modification\n\n    @abstractmethod\n    def _do_fetch(self) -> None:\n\"\"\"Fetch the object from a remote source.\"\"\"\n        pass\n\n    def _in_cache(self) -> bool:\n\"\"\"Return whether object is present in the cache or not.\"\"\"\n        return self._cached_object_path.exists()\n\n    def _is_stale(self) -> bool:\n        # Either cache empty or cached item is too old\n        if not self._in_cache():\n            return True\n        return FetcherBase._time_since_modification(self._cached_object_path\n                                                    ) > datetime.timedelta(seconds=self._expiration_seconds)\n\n    def _update_cache(self, force_update: bool = False) -> bool:\n\"\"\"Update the cache by fetching the target remote object, if stale or forced.\n\n        Args:\n            force_update: force the fetch regardless of staleness.\n\n        Returns:\n            True if update occurred\n        \"\"\"\n        if self._is_stale() or force_update:\n            try:\n                self._do_fetch()\n                return True\n            except Exception as e:\n                raise TrestleError(\n                    f'Cache update failure for {self._uri}.  Please confirm the file is json and not html: {e}.'\n                ) from e  # noqa E501\n        return False\n\n    def get_raw(self, force_update: bool = False) -> Dict[str, Any]:\n\"\"\"Retrieve the raw dictionary representing the underlying object.\"\"\"\n        self._update_cache(force_update)\n        # Return results in the cache, whether yaml or json, or whatever is supported by fs.load_file().\n        try:\n            raw_data = file_utils.load_file(self._cached_object_path)\n        except Exception:\n            try:\n                raw_data = file_utils.load_file(self._cached_object_path)\n            except Exception as e:\n                raise TrestleError(f'Cache get failure for {self._uri}: {e}.') from e\n        return raw_data\n\n    def get_oscal_with_model_type(self,\n                                  model_type: Type[OscalBaseModel],\n                                  force_update: bool = False) -> Optional[OscalBaseModel]:\n\"\"\"Retrieve the cached file as a particular OSCAL model.\n\n        Arguments:\n            model_type: Type[OscalBaseModel] Specifies the OSCAL model type of the fetched object.\n        \"\"\"\n        self._update_cache(force_update)\n        cache_file = self._cached_object_path\n        if not cache_file.exists():\n            raise TrestleError(f'get_oscal failure for {self._uri}')\n\n        try:\n            return model_type.oscal_read(cache_file)\n        except Exception as e:\n            logger.debug(f'get_oscal failed, error loading cache file for {self._uri} as {model_type}')\n            raise TrestleError(f'get_oscal failure for {self._uri}: {e}.') from e\n\n    def get_oscal(self, force_update: bool = False) -> Tuple[OscalBaseModel, str]:\n\"\"\"Retrieve the cached file and model name without knowing its model type.\"\"\"\n        model_dict = self.get_raw(force_update)\n        root_key = parser.root_key(model_dict)\n        model_name = parser.to_full_model_name(root_key)\n        if model_name is None:\n            raise TrestleError(f'Failed cache read of non top level model with root_key {root_key}')\n        return parser.parse_dict(model_dict[root_key], model_name), root_key\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                                                            Intialize fetcher base.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            Path of the trestle workspace, i.e., within which .trestle is to be found.

                                                                            required uri str

                                                                            Reference to the source object to cache.

                                                                            required Source code in trestle/core/remote/cache.py
                                                                            def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Intialize fetcher base.\n\n    Args:\n        trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n        uri: Reference to the source object to cache.\n    \"\"\"\n    logger.debug('Initializing FetcherBase')\n    self._cached_object_path: pathlib.Path\n    self._uri = uri\n    self._trestle_root = trestle_root.resolve()\n    self._trestle_cache_path: pathlib.Path = self._trestle_root / const.TRESTLE_CACHE_DIR\n    # ensure trestle cache directory exists.\n    self._trestle_cache_path.mkdir(exist_ok=True)\n    self._expiration_seconds = const.DAY_SECONDS\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.get_oscal","title":"get_oscal(self, force_update=False)","text":"

                                                                            Retrieve the cached file and model name without knowing its model type.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            def get_oscal(self, force_update: bool = False) -> Tuple[OscalBaseModel, str]:\n\"\"\"Retrieve the cached file and model name without knowing its model type.\"\"\"\n    model_dict = self.get_raw(force_update)\n    root_key = parser.root_key(model_dict)\n    model_name = parser.to_full_model_name(root_key)\n    if model_name is None:\n        raise TrestleError(f'Failed cache read of non top level model with root_key {root_key}')\n    return parser.parse_dict(model_dict[root_key], model_name), root_key\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.get_oscal_with_model_type","title":"get_oscal_with_model_type(self, model_type, force_update=False)","text":"

                                                                            Retrieve the cached file as a particular OSCAL model.

                                                                            Parameters:

                                                                            Name Type Description Default model_type Type[trestle.core.base_model.OscalBaseModel]

                                                                            Type[OscalBaseModel] Specifies the OSCAL model type of the fetched object.

                                                                            required Source code in trestle/core/remote/cache.py
                                                                            def get_oscal_with_model_type(self,\n                              model_type: Type[OscalBaseModel],\n                              force_update: bool = False) -> Optional[OscalBaseModel]:\n\"\"\"Retrieve the cached file as a particular OSCAL model.\n\n    Arguments:\n        model_type: Type[OscalBaseModel] Specifies the OSCAL model type of the fetched object.\n    \"\"\"\n    self._update_cache(force_update)\n    cache_file = self._cached_object_path\n    if not cache_file.exists():\n        raise TrestleError(f'get_oscal failure for {self._uri}')\n\n    try:\n        return model_type.oscal_read(cache_file)\n    except Exception as e:\n        logger.debug(f'get_oscal failed, error loading cache file for {self._uri} as {model_type}')\n        raise TrestleError(f'get_oscal failure for {self._uri}: {e}.') from e\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherBase.get_raw","title":"get_raw(self, force_update=False)","text":"

                                                                            Retrieve the raw dictionary representing the underlying object.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            def get_raw(self, force_update: bool = False) -> Dict[str, Any]:\n\"\"\"Retrieve the raw dictionary representing the underlying object.\"\"\"\n    self._update_cache(force_update)\n    # Return results in the cache, whether yaml or json, or whatever is supported by fs.load_file().\n    try:\n        raw_data = file_utils.load_file(self._cached_object_path)\n    except Exception:\n        try:\n            raw_data = file_utils.load_file(self._cached_object_path)\n        except Exception as e:\n            raise TrestleError(f'Cache get failure for {self._uri}: {e}.') from e\n    return raw_data\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory","title":" FetcherFactory ","text":"

                                                                            Factory method for creating a fetcher.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            class FetcherFactory:\n\"\"\"Factory method for creating a fetcher.\"\"\"\n\n    class UriType(Enum):\n\"\"\"Specify types of URI.\"\"\"\n\n        LOCAL_FILE = 1\n\n        SFTP = 2\n\n        HTTPS = 3\n\n        TRESTLE = 4\n\n    @staticmethod\n    def uri_type_is_not_local(uri_type: UriType) -> bool:\n\"\"\"Determine if the uri type is not local.\"\"\"\n        return uri_type in [FetcherFactory.UriType.SFTP, FetcherFactory.UriType.HTTPS]\n\n    @staticmethod\n    def get_uri_type(uri: str) -> UriType:\n\"\"\"Determine the type of uri.\"\"\"\n        if uri.startswith(const.SFTP_URI):\n            return FetcherFactory.UriType.SFTP\n        if uri.startswith(const.HTTPS_URI):\n            return FetcherFactory.UriType.HTTPS\n        if uri.startswith(const.TRESTLE_HREF_HEADING):\n            return FetcherFactory.UriType.TRESTLE\n        # if we land here, assume it is a local file and may have relative path\n        # but it at least needs a filename with suffix\n        # the most minimal allowed uri is of the form a.yml\n        uri_clean = uri.strip()\n        if uri_clean.startswith('ftp:'):\n            raise TrestleError(f'Invalid uri {uri}  ftp is not supported.  Use sftp instead.')\n        uri_len = len(uri_clean)\n        # at least 5 chars and ending with dot followed by at least 3 chars\n        if uri_len > 4 and 0 < uri_clean.rfind('.') < uri_len - 3:\n            return FetcherFactory.UriType.LOCAL_FILE\n        raise TrestleError(f'Invalid uri not recognized as a readable file path with extension: {uri}')\n\n    @staticmethod\n    def in_trestle_directory(trestle_root: pathlib.Path, uri: str) -> bool:\n\"\"\"Check if in trestle directory when uri may not be a file path.\"\"\"\n        uri_type = FetcherFactory.get_uri_type(uri)\n        if uri_type == FetcherFactory.UriType.TRESTLE:\n            return True\n        if uri_type != FetcherFactory.UriType.LOCAL_FILE:\n            return False\n        try:\n            pathlib.Path(uri).resolve().relative_to(str(trestle_root.resolve()))\n        except Exception:\n            return False\n        return True\n\n    @classmethod\n    def get_fetcher(cls, trestle_root: pathlib.Path, uri: str) -> Union[LocalFetcher, SFTPFetcher, HTTPSFetcher]:\n\"\"\"Return an instantiated fetcher object based on the type of URI.\n\n        Args:\n            trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n            uri: Reference to the remote object to cache.\n\n        Returns:\n            fetcher object for the given URI.\n        \"\"\"\n        fetcher_dict = {\n            FetcherFactory.UriType.LOCAL_FILE: LocalFetcher,\n            FetcherFactory.UriType.SFTP: SFTPFetcher,\n            FetcherFactory.UriType.HTTPS: HTTPSFetcher,\n            FetcherFactory.UriType.TRESTLE: LocalFetcher,\n        }\n        uri_type = cls.get_uri_type(uri)\n        return fetcher_dict[uri_type](trestle_root, uri)  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.UriType","title":" UriType (Enum) ","text":"

                                                                            Specify types of URI.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            class UriType(Enum):\n\"\"\"Specify types of URI.\"\"\"\n\n    LOCAL_FILE = 1\n\n    SFTP = 2\n\n    HTTPS = 3\n\n    TRESTLE = 4\n
                                                                            HTTPS \u00a4 LOCAL_FILE \u00a4 SFTP \u00a4 TRESTLE \u00a4"},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.get_fetcher","title":"get_fetcher(trestle_root, uri) classmethod","text":"

                                                                            Return an instantiated fetcher object based on the type of URI.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            Path of the trestle workspace, i.e., within which .trestle is to be found.

                                                                            required uri str

                                                                            Reference to the remote object to cache.

                                                                            required

                                                                            Returns:

                                                                            Type Description Union[trestle.core.remote.cache.LocalFetcher, trestle.core.remote.cache.SFTPFetcher, trestle.core.remote.cache.HTTPSFetcher]

                                                                            fetcher object for the given URI.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            @classmethod\ndef get_fetcher(cls, trestle_root: pathlib.Path, uri: str) -> Union[LocalFetcher, SFTPFetcher, HTTPSFetcher]:\n\"\"\"Return an instantiated fetcher object based on the type of URI.\n\n    Args:\n        trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n        uri: Reference to the remote object to cache.\n\n    Returns:\n        fetcher object for the given URI.\n    \"\"\"\n    fetcher_dict = {\n        FetcherFactory.UriType.LOCAL_FILE: LocalFetcher,\n        FetcherFactory.UriType.SFTP: SFTPFetcher,\n        FetcherFactory.UriType.HTTPS: HTTPSFetcher,\n        FetcherFactory.UriType.TRESTLE: LocalFetcher,\n    }\n    uri_type = cls.get_uri_type(uri)\n    return fetcher_dict[uri_type](trestle_root, uri)  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.get_uri_type","title":"get_uri_type(uri) staticmethod","text":"

                                                                            Determine the type of uri.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            @staticmethod\ndef get_uri_type(uri: str) -> UriType:\n\"\"\"Determine the type of uri.\"\"\"\n    if uri.startswith(const.SFTP_URI):\n        return FetcherFactory.UriType.SFTP\n    if uri.startswith(const.HTTPS_URI):\n        return FetcherFactory.UriType.HTTPS\n    if uri.startswith(const.TRESTLE_HREF_HEADING):\n        return FetcherFactory.UriType.TRESTLE\n    # if we land here, assume it is a local file and may have relative path\n    # but it at least needs a filename with suffix\n    # the most minimal allowed uri is of the form a.yml\n    uri_clean = uri.strip()\n    if uri_clean.startswith('ftp:'):\n        raise TrestleError(f'Invalid uri {uri}  ftp is not supported.  Use sftp instead.')\n    uri_len = len(uri_clean)\n    # at least 5 chars and ending with dot followed by at least 3 chars\n    if uri_len > 4 and 0 < uri_clean.rfind('.') < uri_len - 3:\n        return FetcherFactory.UriType.LOCAL_FILE\n    raise TrestleError(f'Invalid uri not recognized as a readable file path with extension: {uri}')\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.in_trestle_directory","title":"in_trestle_directory(trestle_root, uri) staticmethod","text":"

                                                                            Check if in trestle directory when uri may not be a file path.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            @staticmethod\ndef in_trestle_directory(trestle_root: pathlib.Path, uri: str) -> bool:\n\"\"\"Check if in trestle directory when uri may not be a file path.\"\"\"\n    uri_type = FetcherFactory.get_uri_type(uri)\n    if uri_type == FetcherFactory.UriType.TRESTLE:\n        return True\n    if uri_type != FetcherFactory.UriType.LOCAL_FILE:\n        return False\n    try:\n        pathlib.Path(uri).resolve().relative_to(str(trestle_root.resolve()))\n    except Exception:\n        return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.FetcherFactory.uri_type_is_not_local","title":"uri_type_is_not_local(uri_type) staticmethod","text":"

                                                                            Determine if the uri type is not local.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            @staticmethod\ndef uri_type_is_not_local(uri_type: UriType) -> bool:\n\"\"\"Determine if the uri type is not local.\"\"\"\n    return uri_type in [FetcherFactory.UriType.SFTP, FetcherFactory.UriType.HTTPS]\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.HTTPSFetcher","title":" HTTPSFetcher (FetcherBase) ","text":"

                                                                            Fetcher for https content.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            class HTTPSFetcher(FetcherBase):\n\"\"\"Fetcher for https content.\"\"\"\n\n    # Use request: https://requests.readthedocs.io/en/master/\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize HTTPS fetcher.\"\"\"\n        logger.debug('Initializing HTTPSFetcher')\n        super().__init__(trestle_root, uri)\n        self._username = None\n        self._password = None\n        u = parse.urlparse(self._uri)\n        self._url = uri\n        # If the either the username or password is omitted in the URI, then the other becomes ''\n        # so we test for either None or ''.\n        if u.username != '' and u.username is not None:\n            # This also checks for invalid environment variable name (IEEE 1003.1)\n            if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.username) or u.username == '{{_}}':\n                raise TrestleError(\n                    'Cache request for invalid input URI: '\n                    f'username must refer to an environment variable using moustache {self._uri}'\n                )\n            username_var = u.username[2:-2]\n            if username_var not in os.environ:\n                raise TrestleError(\n                    f'Cache request for invalid input URI: username not found in the environment {self._uri}'\n                )\n            self._username = os.environ[username_var]\n        if u.password != '' and u.password is not None:  # noqa S105\n            if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.password) or u.password == '{{_}}':  # noqa S105\n                raise TrestleError(\n                    'Cache request for invalid input URI: '\n                    f'password must refer to an environment variable using moustache {self._uri}'\n                )\n            password_var = u.password[2:-2]\n            if password_var not in os.environ:\n                raise TrestleError(\n                    'Cache request for invalid input URI: '\n                    f'password not found in the environment {self._uri}'\n                )\n            self._password = os.environ[password_var]\n        if self._username and (self._password == '' or self._password is None):  # noqa S105\n            raise TrestleError(\n                f'Cache request for invalid input URI: username found '\n                f'but password not found via environment variable {self._uri}'\n            )\n        if self._password and not self._username:\n            raise TrestleError(\n                f'Cache request for invalid input URI: password found '\n                f'but username not found via environment variable {self._uri}'\n            )\n        if u.hostname is None:\n            raise TrestleError(f'Cache request for {self._uri} requires hostname')\n        https_cached_dir = self._trestle_cache_path / u.hostname\n        # Skip any number of back- or forward slashes preceding the URI path (u.path)\n        path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n        https_cached_dir = https_cached_dir / path_parent\n        https_cached_dir.mkdir(parents=True, exist_ok=True)\n        self._cached_object_path = https_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n\n    def _do_fetch(self) -> None:\n        auth = None\n        verify = None\n        # This order reflects requests library behavior: REQUESTS_CA_BUNDLE comes first.\n        for env_var_name in ['REQUESTS_CA_BUNDLE', 'CURL_CA_BUNDLE']:\n            if env_var_name in os.environ:\n                if pathlib.Path(os.environ[env_var_name]).exists():\n                    verify = os.environ[env_var_name]\n                    break\n                else:\n                    err_str = f'Env var ${env_var_name} found but path does not exist: {os.environ[env_var_name]}'\n                    logger.warning(err_str)\n                    raise TrestleError(f'Cache update failure with bad inputenv var: {err_str}')\n        if self._username is not None and self._password is not None:\n            auth = HTTPBasicAuth(self._username, self._password)\n\n        try:\n            response = requests.get(self._url, auth=auth, verify=verify, timeout=30)\n        except Exception as e:\n            raise TrestleError(f'Cache update failure to connect via HTTPS: {self._url} ({e})')\n\n        if response.status_code == 200:\n            try:\n                result = response.text\n            except Exception as err:\n                raise TrestleError(f'Cache update failure reading response via HTTPS: {self._url} ({err})')\n            else:\n                self._cached_object_path.write_text(result, encoding=const.FILE_ENCODING)\n        else:\n            raise TrestleError(f'GET returned code {response.status_code}: {self._uri}')\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.HTTPSFetcher-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.HTTPSFetcher.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                                                            Initialize HTTPS fetcher.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize HTTPS fetcher.\"\"\"\n    logger.debug('Initializing HTTPSFetcher')\n    super().__init__(trestle_root, uri)\n    self._username = None\n    self._password = None\n    u = parse.urlparse(self._uri)\n    self._url = uri\n    # If the either the username or password is omitted in the URI, then the other becomes ''\n    # so we test for either None or ''.\n    if u.username != '' and u.username is not None:\n        # This also checks for invalid environment variable name (IEEE 1003.1)\n        if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.username) or u.username == '{{_}}':\n            raise TrestleError(\n                'Cache request for invalid input URI: '\n                f'username must refer to an environment variable using moustache {self._uri}'\n            )\n        username_var = u.username[2:-2]\n        if username_var not in os.environ:\n            raise TrestleError(\n                f'Cache request for invalid input URI: username not found in the environment {self._uri}'\n            )\n        self._username = os.environ[username_var]\n    if u.password != '' and u.password is not None:  # noqa S105\n        if not re.match('{{[a-zA-Z_][a-zA-Z0-9_]*}}', u.password) or u.password == '{{_}}':  # noqa S105\n            raise TrestleError(\n                'Cache request for invalid input URI: '\n                f'password must refer to an environment variable using moustache {self._uri}'\n            )\n        password_var = u.password[2:-2]\n        if password_var not in os.environ:\n            raise TrestleError(\n                'Cache request for invalid input URI: '\n                f'password not found in the environment {self._uri}'\n            )\n        self._password = os.environ[password_var]\n    if self._username and (self._password == '' or self._password is None):  # noqa S105\n        raise TrestleError(\n            f'Cache request for invalid input URI: username found '\n            f'but password not found via environment variable {self._uri}'\n        )\n    if self._password and not self._username:\n        raise TrestleError(\n            f'Cache request for invalid input URI: password found '\n            f'but username not found via environment variable {self._uri}'\n        )\n    if u.hostname is None:\n        raise TrestleError(f'Cache request for {self._uri} requires hostname')\n    https_cached_dir = self._trestle_cache_path / u.hostname\n    # Skip any number of back- or forward slashes preceding the URI path (u.path)\n    path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n    https_cached_dir = https_cached_dir / path_parent\n    https_cached_dir.mkdir(parents=True, exist_ok=True)\n    self._cached_object_path = https_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.LocalFetcher","title":" LocalFetcher (FetcherBase) ","text":"

                                                                            Fetcher for local content.

                                                                            Used for both file:/// and C:\\ or C:/ type paths, but the path must be absolute. Also used for trestle:// files present in the current trestle root.

                                                                            If file:/// is used on a Windows system, it must be followed by C:/ or other drive letter to be sure it is an absolute path, e.g. file:///C:/Users/Default/Documents/profile.json. The drive letter may be lowercase. LocalFetcher does not do any caching and assumes the file is quickly accessible.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            class LocalFetcher(FetcherBase):\nr\"\"\"Fetcher for local content.\n\n    Used for both file:/// and C:\\\\ or C:/ type paths, but the path must be absolute.\n    Also used for trestle:// files present in the current trestle root.\n\n    If file:/// is used on a Windows system, it must be followed by C:/ or other drive letter\n    to be sure it is an absolute path, e.g. file:///C:/Users/Default/Documents/profile.json.\n    The drive letter may be lowercase.\n    LocalFetcher does not do any caching and assumes the file is quickly accessible.\n    \"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize local fetcher.\n\n        Args:\n            trestle_root: trestle root path\n            uri: Reference to the file in the local filesystem to cache, which must be outside trestle_root.\n        \"\"\"\n        super().__init__(trestle_root, uri)\n\n        # Handle as file:/// form\n        if uri.startswith(const.FILE_URI):\n            # strip off entire header including /\n            uri = uri[len(const.FILE_URI):]\n\n            # if it has a drive letter don't add / to front\n            uri = uri if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri) else '/' + uri\n        elif uri.startswith(const.TRESTLE_HREF_HEADING):\n            uri = str(trestle_root / uri[len(const.TRESTLE_HREF_HEADING):])\n            self._abs_path = pathlib.Path(uri).resolve()\n            self._cached_object_path = self._abs_path\n            return\n\n        # now the URI should be either unix / style or windows C:/ style.  It may be relative.\n\n        if ':' in uri and platform.system() != const.WINDOWS_PLATFORM_STR:\n            raise TrestleError(f'Cannot have : in uri on non-Windows system unless ftps, https or trestle: {uri}')\n\n        # if it has a drive letter but no / after it, it is not absolute\n        if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri):\n            if platform.system() != const.WINDOWS_PLATFORM_STR:\n                raise TrestleError(f'Cannot cache Windows paths on non-Windows system. {uri}')\n\n        # store the abs path to the file for fetching\n        # if this is a windows file it will have a drive letter at start after resolve\n        try:\n            self._abs_path = pathlib.Path(uri).resolve()\n        except Exception:\n            raise TrestleError(f'The uri provided is invalid or unresolvable as a file path: {uri}')\n\n        # set the cached path to be the actual file path\n        self._cached_object_path = self._abs_path\n\n    def _is_stale(self) -> bool:\n        # Local file is always stale.\n        return True\n\n    def _do_fetch(self) -> None:\n\"\"\"No need to fetch since using actual file path.\"\"\"\n        pass\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.LocalFetcher-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.LocalFetcher.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                                                            Initialize local fetcher.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            trestle root path

                                                                            required uri str

                                                                            Reference to the file in the local filesystem to cache, which must be outside trestle_root.

                                                                            required Source code in trestle/core/remote/cache.py
                                                                            def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize local fetcher.\n\n    Args:\n        trestle_root: trestle root path\n        uri: Reference to the file in the local filesystem to cache, which must be outside trestle_root.\n    \"\"\"\n    super().__init__(trestle_root, uri)\n\n    # Handle as file:/// form\n    if uri.startswith(const.FILE_URI):\n        # strip off entire header including /\n        uri = uri[len(const.FILE_URI):]\n\n        # if it has a drive letter don't add / to front\n        uri = uri if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri) else '/' + uri\n    elif uri.startswith(const.TRESTLE_HREF_HEADING):\n        uri = str(trestle_root / uri[len(const.TRESTLE_HREF_HEADING):])\n        self._abs_path = pathlib.Path(uri).resolve()\n        self._cached_object_path = self._abs_path\n        return\n\n    # now the URI should be either unix / style or windows C:/ style.  It may be relative.\n\n    if ':' in uri and platform.system() != const.WINDOWS_PLATFORM_STR:\n        raise TrestleError(f'Cannot have : in uri on non-Windows system unless ftps, https or trestle: {uri}')\n\n    # if it has a drive letter but no / after it, it is not absolute\n    if re.match(const.WINDOWS_DRIVE_LETTER_REGEX, uri):\n        if platform.system() != const.WINDOWS_PLATFORM_STR:\n            raise TrestleError(f'Cannot cache Windows paths on non-Windows system. {uri}')\n\n    # store the abs path to the file for fetching\n    # if this is a windows file it will have a drive letter at start after resolve\n    try:\n        self._abs_path = pathlib.Path(uri).resolve()\n    except Exception:\n        raise TrestleError(f'The uri provided is invalid or unresolvable as a file path: {uri}')\n\n    # set the cached path to be the actual file path\n    self._cached_object_path = self._abs_path\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.SFTPFetcher","title":" SFTPFetcher (FetcherBase) ","text":"

                                                                            Fetcher for SFTP content.

                                                                            Source code in trestle/core/remote/cache.py
                                                                            class SFTPFetcher(FetcherBase):\n\"\"\"Fetcher for SFTP content.\"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize SFTP fetcher. Update the expected cache path as per caching specs.\n\n        Args:\n            trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n            uri: Reference to the remote file to cache that can be fetched using the sftp:// scheme.\n        \"\"\"\n        logger.debug(f'initialize SFTPFetcher for uri {uri}')\n        super().__init__(trestle_root, uri)\n        # Is this a valid URI, however? Username and password are optional, of course.\n        try:\n            u = parse.urlparse(self._uri)\n        except Exception as e:\n            logger.warning(f'SFTP fetcher unable to parse uri {self._uri} error {e}')\n            raise TrestleError(f'Unable to parse malformed url {self._uri} error {e}')\n        logger.debug(f'SFTP fetcher with parsed uri {u}')\n        if not u.hostname:\n            logger.debug('SFTP fetcher uri missing hostname')\n            logger.warning(f'Malformed URI, cannot parse hostname in URL {self._uri}')\n            raise TrestleError(f'Cache request for invalid input URI: missing hostname {self._uri}')\n        if not u.path:\n            logger.debug('SFTP fetcher uri missing path')\n            logger.warning(f'Malformed URI, cannot parse path in URL {self._uri}')\n            raise TrestleError(f'Cache request for invalid input URI: missing file path {self._uri}')\n\n        sftp_cached_dir = self._trestle_cache_path / u.hostname\n        # Skip any number of back- or forward slashes preceding the URL path (u.path)\n        path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n        sftp_cached_dir = sftp_cached_dir / path_parent\n        sftp_cached_dir.mkdir(parents=True, exist_ok=True)\n        self._cached_object_path = sftp_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n\n    def _do_fetch(self) -> None:\n\"\"\"Fetch remote object and update the cache if appropriate and possible to do so.\n\n        Authentication relies on the user's private key being either active via ssh-agent or\n        supplied via environment variable SSH_KEY. In the latter case, it must not require a passphrase prompt.\n        \"\"\"\n        u = parse.urlparse(self._uri)\n        client = paramiko.SSHClient()\n        # Must pick up host keys from the default known_hosts on this environment:\n        try:\n            client.load_system_host_keys()\n        except Exception as e:\n            raise TrestleError(f'Cache update failure for {self._uri}: {e}.')\n        # Use the supplied private key file if given, or look for keys in default path.\n        if 'SSH_KEY' in os.environ:\n            pkey = paramiko.RSAKey.from_private_key(StringIO(os.environ['SSH_KEY']))\n            look_for_keys = False\n        else:\n            pkey = None\n            look_for_keys = True\n\n        username = getpass.getuser() if not u.username else u.username\n        try:\n            client.connect(\n                u.hostname,\n                username=username,\n                password=u.password,\n                pkey=pkey,\n                look_for_keys=look_for_keys,\n                port=22 if not u.port else u.port,\n            )\n        except Exception as e:\n            raise TrestleError(f'Cache update failure to connect via SSH: {u.hostname}: {e}.')\n\n        try:\n            sftp_client = client.open_sftp()\n        except Exception as e:\n            raise TrestleError(f'Cache update failure to open sftp for {u.hostname}: {e}.')\n\n        localpath = self._cached_object_path\n        try:\n            sftp_client.get(remotepath=u.path[1:], localpath=(localpath.__str__()))\n        except Exception as e:\n            raise TrestleError(f'Error getting remote resource {self._uri} into cache {localpath}: {e}')\n
                                                                            "},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.SFTPFetcher-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.remote.cache/#trestle.core.remote.cache.SFTPFetcher.__init__","title":"__init__(self, trestle_root, uri) special","text":"

                                                                            Initialize SFTP fetcher. Update the expected cache path as per caching specs.

                                                                            Parameters:

                                                                            Name Type Description Default trestle_root Path

                                                                            Path of the trestle workspace, i.e., within which .trestle is to be found.

                                                                            required uri str

                                                                            Reference to the remote file to cache that can be fetched using the sftp:// scheme.

                                                                            required Source code in trestle/core/remote/cache.py
                                                                            def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:\n\"\"\"Initialize SFTP fetcher. Update the expected cache path as per caching specs.\n\n    Args:\n        trestle_root: Path of the trestle workspace, i.e., within which .trestle is to be found.\n        uri: Reference to the remote file to cache that can be fetched using the sftp:// scheme.\n    \"\"\"\n    logger.debug(f'initialize SFTPFetcher for uri {uri}')\n    super().__init__(trestle_root, uri)\n    # Is this a valid URI, however? Username and password are optional, of course.\n    try:\n        u = parse.urlparse(self._uri)\n    except Exception as e:\n        logger.warning(f'SFTP fetcher unable to parse uri {self._uri} error {e}')\n        raise TrestleError(f'Unable to parse malformed url {self._uri} error {e}')\n    logger.debug(f'SFTP fetcher with parsed uri {u}')\n    if not u.hostname:\n        logger.debug('SFTP fetcher uri missing hostname')\n        logger.warning(f'Malformed URI, cannot parse hostname in URL {self._uri}')\n        raise TrestleError(f'Cache request for invalid input URI: missing hostname {self._uri}')\n    if not u.path:\n        logger.debug('SFTP fetcher uri missing path')\n        logger.warning(f'Malformed URI, cannot parse path in URL {self._uri}')\n        raise TrestleError(f'Cache request for invalid input URI: missing file path {self._uri}')\n\n    sftp_cached_dir = self._trestle_cache_path / u.hostname\n    # Skip any number of back- or forward slashes preceding the URL path (u.path)\n    path_parent = pathlib.Path(u.path[re.search('[^/\\\\\\\\]', u.path).span()[0]:]).parent\n    sftp_cached_dir = sftp_cached_dir / path_parent\n    sftp_cached_dir.mkdir(parents=True, exist_ok=True)\n    self._cached_object_path = sftp_cached_dir / pathlib.Path(pathlib.Path(u.path).name)\n
                                                                            "},{"location":"api_reference/trestle.core.repository/","title":"repository","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository","title":"trestle.core.repository","text":"

                                                                            Trestle Repository APIs.

                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring","title":" AgileAuthoring (Repository) ","text":"

                                                                            AgileAuthoring extends the Repository class for performing authoring specific operations on Trestle repository.

                                                                            This class provides a set of APIs to perform generate and assemble authoring operations in the trestle repository rather than using the command line.

                                                                            Source code in trestle/core/repository.py
                                                                            class AgileAuthoring(Repository):\n\"\"\"\n    AgileAuthoring extends the Repository class for performing authoring specific operations on Trestle repository.\n\n    This class provides a set of APIs to perform generate and assemble authoring operations in the trestle repository\n    rather than using the command line.\n\n    \"\"\"\n\n    def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n        super().__init__(root_dir)\n\n    def assemble_catalog_markdown(\n        self,\n        name: str,\n        output: str,\n        markdown_dir: str,\n        set_parameters: bool = False,\n        regenerate: bool = False,\n        version: Optional[str] = None\n    ) -> bool:\n\"\"\"Assemble catalog markdown into OSCAL Catalog in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type catalog.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            trestle_root=self.root_dir,\n            set_parameters=set_parameters,\n            regenerate=regenerate,\n            version=version,\n            verbose=verbose\n        )\n\n        try:\n            ret = catalogauthorcmd.CatalogAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling catalog {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def assemble_profile_markdown(\n        self,\n        name: str,\n        output: str,\n        markdown_dir: str,\n        set_parameters: bool = False,\n        regenerate: bool = False,\n        version: Optional[str] = None,\n        sections: Optional[str] = None,\n        required_sections: Optional[str] = None,\n        allowed_sections: Optional[str] = None\n    ) -> bool:\n\"\"\"Assemble profile markdown into OSCAL Profile in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type profile.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            trestle_root=self.root_dir,\n            set_parameters=set_parameters,\n            regenerate=regenerate,\n            version=version,\n            sections=sections,\n            required_sections=required_sections,\n            allowed_sections=allowed_sections,\n            verbose=verbose\n        )\n\n        try:\n            ret = profileauthorcmd.ProfileAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling profile {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def assemble_component_definition_markdown(\n        self, name: str, output: str, markdown_dir: str, regenerate: bool = False, version: str = ''\n    ) -> bool:\n\"\"\"Assemble component definition markdown into OSCAL Component Definition in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type component definition.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            trestle_root=self.root_dir,\n            regenerate=regenerate,\n            version=version,\n            verbose=verbose\n        )\n\n        try:\n            ret = componentauthorcmd.ComponentAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling component definition {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def assemble_ssp_markdown(\n        self,\n        name: str,\n        output: str,\n        markdown_dir: str,\n        compdefs: str,\n        regenerate: bool = False,\n        version: Optional[str] = None\n    ) -> bool:\n\"\"\"Assemble ssp markdown into OSCAL SSP in JSON.\"\"\"\n        logger.debug(f'Assembling model {name} of type ssp.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            markdown=markdown_dir,\n            compdefs=compdefs,\n            trestle_root=self.root_dir,\n            regenerate=regenerate,\n            version=version,\n            verbose=verbose\n        )\n\n        try:\n            ret = sspauthorcmd.SSPAssemble()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error assembling ssp {name}: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def generate_catalog_markdown(\n        self,\n        name: str,\n        output: str,\n        force_overwrite: bool = False,\n        yaml_header: Optional[str] = None,\n        overwrite_header_values: bool = False\n    ) -> bool:\n\"\"\"Generate catalog markdown from OSCAL Catalog in JSON.\"\"\"\n        logger.debug(f'Generating markdown for {name} of type catalog.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            trestle_root=self.root_dir,\n            force_overwrite=force_overwrite,\n            yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            verbose=verbose\n        )\n\n        try:\n            ret = catalogauthorcmd.CatalogGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error generate markdown for catalog {name}: {e}')\n\n        logger.debug(f'Model {name} markdown generated successfully.')\n        return success\n\n    def generate_profile_markdown(\n        self,\n        name: str,\n        output: str,\n        force_overwrite: bool = False,\n        yaml_header: Optional[str] = None,\n        overwrite_header_values: bool = False,\n        sections: Optional[str] = None,\n        required_sections: Optional[str] = None\n    ) -> bool:\n\"\"\"Generate profile markdown from OSCAL Profile in JSON.\"\"\"\n        logger.debug(f'Generating markdown for {name} of type profile.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name,\n            output=output,\n            trestle_root=self.root_dir,\n            force_overwrite=force_overwrite,\n            yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            sections=sections,\n            required_sections=required_sections,\n            verbose=verbose\n        )\n\n        try:\n            ret = profileauthorcmd.ProfileGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error generate markdown for profile {name}: {e}')\n\n        logger.debug(f'Model {name} markdown generated successfully.')\n        return success\n\n    def generate_component_definition_markdown(\n        self,\n        name: str,\n        output: str,\n        force_overwrite: bool = False,\n    ) -> bool:\n\"\"\"Generate component definition markdown from OSCAL Component Definition in JSON.\"\"\"\n        logger.debug(f'Generating markdown for {name} of type component definition.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            name=name, output=output, trestle_root=self.root_dir, force_overwrite=force_overwrite, verbose=verbose\n        )\n\n        try:\n            ret = componentauthorcmd.ComponentGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error generating markdown for component definition {name}: {e}')\n\n        logger.debug(f'Model {name} markdown generated successfully.')\n        return success\n\n    def generate_ssp_markdown(\n        self,\n        profile: str,\n        output: str,\n        compdefs: str,\n        leveraged_ssp: Optional[str] = None,\n        force_overwrite: bool = False,\n        include_all_parts: bool = False,\n        yaml_header: Optional[str] = None,\n        overwrite_header_values: bool = False\n    ) -> bool:\n\"\"\"Generate ssp markdown from OSCAL Profile and Component Definitions.\"\"\"\n        logger.debug(f'Generating markdown for {output} of type ssp.')\n        success = False\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            profile=profile,\n            output=output,\n            compdefs=compdefs,\n            leveraged_ssp=leveraged_ssp,\n            trestle_root=self.root_dir,\n            force_overwrite=force_overwrite,\n            include_all_parts=include_all_parts,\n            yaml_header=yaml_header,\n            overwrite_header_values=overwrite_header_values,\n            verbose=verbose\n        )\n\n        try:\n            ret = sspauthorcmd.SSPGenerate()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in generating markdown for ssp {output}: {e}')\n\n        logger.debug(f'Model {output} markdown generated successfully.')\n        return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.__init__","title":"__init__(self, root_dir) special","text":"Source code in trestle/core/repository.py
                                                                            def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n    super().__init__(root_dir)\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_catalog_markdown","title":"assemble_catalog_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version=None)","text":"

                                                                            Assemble catalog markdown into OSCAL Catalog in JSON.

                                                                            Source code in trestle/core/repository.py
                                                                            def assemble_catalog_markdown(\n    self,\n    name: str,\n    output: str,\n    markdown_dir: str,\n    set_parameters: bool = False,\n    regenerate: bool = False,\n    version: Optional[str] = None\n) -> bool:\n\"\"\"Assemble catalog markdown into OSCAL Catalog in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type catalog.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        trestle_root=self.root_dir,\n        set_parameters=set_parameters,\n        regenerate=regenerate,\n        version=version,\n        verbose=verbose\n    )\n\n    try:\n        ret = catalogauthorcmd.CatalogAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling catalog {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_component_definition_markdown","title":"assemble_component_definition_markdown(self, name, output, markdown_dir, regenerate=False, version='')","text":"

                                                                            Assemble component definition markdown into OSCAL Component Definition in JSON.

                                                                            Source code in trestle/core/repository.py
                                                                            def assemble_component_definition_markdown(\n    self, name: str, output: str, markdown_dir: str, regenerate: bool = False, version: str = ''\n) -> bool:\n\"\"\"Assemble component definition markdown into OSCAL Component Definition in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type component definition.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        trestle_root=self.root_dir,\n        regenerate=regenerate,\n        version=version,\n        verbose=verbose\n    )\n\n    try:\n        ret = componentauthorcmd.ComponentAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling component definition {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_profile_markdown","title":"assemble_profile_markdown(self, name, output, markdown_dir, set_parameters=False, regenerate=False, version=None, sections=None, required_sections=None, allowed_sections=None)","text":"

                                                                            Assemble profile markdown into OSCAL Profile in JSON.

                                                                            Source code in trestle/core/repository.py
                                                                            def assemble_profile_markdown(\n    self,\n    name: str,\n    output: str,\n    markdown_dir: str,\n    set_parameters: bool = False,\n    regenerate: bool = False,\n    version: Optional[str] = None,\n    sections: Optional[str] = None,\n    required_sections: Optional[str] = None,\n    allowed_sections: Optional[str] = None\n) -> bool:\n\"\"\"Assemble profile markdown into OSCAL Profile in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type profile.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        trestle_root=self.root_dir,\n        set_parameters=set_parameters,\n        regenerate=regenerate,\n        version=version,\n        sections=sections,\n        required_sections=required_sections,\n        allowed_sections=allowed_sections,\n        verbose=verbose\n    )\n\n    try:\n        ret = profileauthorcmd.ProfileAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling profile {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.assemble_ssp_markdown","title":"assemble_ssp_markdown(self, name, output, markdown_dir, compdefs, regenerate=False, version=None)","text":"

                                                                            Assemble ssp markdown into OSCAL SSP in JSON.

                                                                            Source code in trestle/core/repository.py
                                                                            def assemble_ssp_markdown(\n    self,\n    name: str,\n    output: str,\n    markdown_dir: str,\n    compdefs: str,\n    regenerate: bool = False,\n    version: Optional[str] = None\n) -> bool:\n\"\"\"Assemble ssp markdown into OSCAL SSP in JSON.\"\"\"\n    logger.debug(f'Assembling model {name} of type ssp.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        markdown=markdown_dir,\n        compdefs=compdefs,\n        trestle_root=self.root_dir,\n        regenerate=regenerate,\n        version=version,\n        verbose=verbose\n    )\n\n    try:\n        ret = sspauthorcmd.SSPAssemble()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error assembling ssp {name}: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_catalog_markdown","title":"generate_catalog_markdown(self, name, output, force_overwrite=False, yaml_header=None, overwrite_header_values=False)","text":"

                                                                            Generate catalog markdown from OSCAL Catalog in JSON.

                                                                            Source code in trestle/core/repository.py
                                                                            def generate_catalog_markdown(\n    self,\n    name: str,\n    output: str,\n    force_overwrite: bool = False,\n    yaml_header: Optional[str] = None,\n    overwrite_header_values: bool = False\n) -> bool:\n\"\"\"Generate catalog markdown from OSCAL Catalog in JSON.\"\"\"\n    logger.debug(f'Generating markdown for {name} of type catalog.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        trestle_root=self.root_dir,\n        force_overwrite=force_overwrite,\n        yaml_header=yaml_header,\n        overwrite_header_values=overwrite_header_values,\n        verbose=verbose\n    )\n\n    try:\n        ret = catalogauthorcmd.CatalogGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error generate markdown for catalog {name}: {e}')\n\n    logger.debug(f'Model {name} markdown generated successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_component_definition_markdown","title":"generate_component_definition_markdown(self, name, output, force_overwrite=False)","text":"

                                                                            Generate component definition markdown from OSCAL Component Definition in JSON.

                                                                            Source code in trestle/core/repository.py
                                                                            def generate_component_definition_markdown(\n    self,\n    name: str,\n    output: str,\n    force_overwrite: bool = False,\n) -> bool:\n\"\"\"Generate component definition markdown from OSCAL Component Definition in JSON.\"\"\"\n    logger.debug(f'Generating markdown for {name} of type component definition.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name, output=output, trestle_root=self.root_dir, force_overwrite=force_overwrite, verbose=verbose\n    )\n\n    try:\n        ret = componentauthorcmd.ComponentGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error generating markdown for component definition {name}: {e}')\n\n    logger.debug(f'Model {name} markdown generated successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_profile_markdown","title":"generate_profile_markdown(self, name, output, force_overwrite=False, yaml_header=None, overwrite_header_values=False, sections=None, required_sections=None)","text":"

                                                                            Generate profile markdown from OSCAL Profile in JSON.

                                                                            Source code in trestle/core/repository.py
                                                                            def generate_profile_markdown(\n    self,\n    name: str,\n    output: str,\n    force_overwrite: bool = False,\n    yaml_header: Optional[str] = None,\n    overwrite_header_values: bool = False,\n    sections: Optional[str] = None,\n    required_sections: Optional[str] = None\n) -> bool:\n\"\"\"Generate profile markdown from OSCAL Profile in JSON.\"\"\"\n    logger.debug(f'Generating markdown for {name} of type profile.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        name=name,\n        output=output,\n        trestle_root=self.root_dir,\n        force_overwrite=force_overwrite,\n        yaml_header=yaml_header,\n        overwrite_header_values=overwrite_header_values,\n        sections=sections,\n        required_sections=required_sections,\n        verbose=verbose\n    )\n\n    try:\n        ret = profileauthorcmd.ProfileGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error generate markdown for profile {name}: {e}')\n\n    logger.debug(f'Model {name} markdown generated successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.AgileAuthoring.generate_ssp_markdown","title":"generate_ssp_markdown(self, profile, output, compdefs, leveraged_ssp=None, force_overwrite=False, include_all_parts=False, yaml_header=None, overwrite_header_values=False)","text":"

                                                                            Generate ssp markdown from OSCAL Profile and Component Definitions.

                                                                            Source code in trestle/core/repository.py
                                                                            def generate_ssp_markdown(\n    self,\n    profile: str,\n    output: str,\n    compdefs: str,\n    leveraged_ssp: Optional[str] = None,\n    force_overwrite: bool = False,\n    include_all_parts: bool = False,\n    yaml_header: Optional[str] = None,\n    overwrite_header_values: bool = False\n) -> bool:\n\"\"\"Generate ssp markdown from OSCAL Profile and Component Definitions.\"\"\"\n    logger.debug(f'Generating markdown for {output} of type ssp.')\n    success = False\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        profile=profile,\n        output=output,\n        compdefs=compdefs,\n        leveraged_ssp=leveraged_ssp,\n        trestle_root=self.root_dir,\n        force_overwrite=force_overwrite,\n        include_all_parts=include_all_parts,\n        yaml_header=yaml_header,\n        overwrite_header_values=overwrite_header_values,\n        verbose=verbose\n    )\n\n    try:\n        ret = sspauthorcmd.SSPGenerate()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in generating markdown for ssp {output}: {e}')\n\n    logger.debug(f'Model {output} markdown generated successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL","title":" ManagedOSCAL ","text":"

                                                                            Object representing OSCAL models in repository for programmatic manipulation.

                                                                            Source code in trestle/core/repository.py
                                                                            class ManagedOSCAL:\n\"\"\"Object representing OSCAL models in repository for programmatic manipulation.\"\"\"\n\n    def __init__(self, root_dir: pathlib.Path, model_type: Type[OscalBaseModel], name: str) -> None:\n\"\"\"Initialize repository OSCAL model object.\"\"\"\n        if not file_utils.is_valid_project_root(root_dir):\n            raise TrestleError(f'Provided root directory {str(root_dir)} is not a valid Trestle root directory.')\n        self.root_dir = root_dir\n        self.model_type = model_type\n        self.model_name = name\n\n        # set model alais and dir\n        self.model_alias = classname_to_alias(self.model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(self.model_alias) is None:\n            raise TrestleError(f'Given model {self.model_alias} is not a top level model.')\n\n        plural_path = ModelUtils.model_type_to_model_dir(self.model_alias)\n        self.model_dir = self.root_dir / plural_path / self.model_name\n\n        if not self.model_dir.exists() or not self.model_dir.is_dir():\n            raise TrestleError(f'Model dir {self.model_name} does not exist.')\n\n        file_content_type = FileContentType.path_to_content_type(self.model_dir / self.model_alias)\n        if file_content_type == FileContentType.UNKNOWN:\n            raise TrestleError(f'Model file for model {self.model_name} does not exist.')\n        self.file_content_type = file_content_type\n\n        filepath = pathlib.Path(\n            self.model_dir,\n            self.model_alias + FileContentType.path_to_file_extension(self.model_dir / self.model_alias)\n        )\n\n        self.filepath = filepath\n\n    def read(self) -> OscalBaseModel:\n\"\"\"Read OSCAL model from repository.\"\"\"\n        logger.debug(f'Reading model {self.model_name}.')\n        model = load_validate_model_path(self.root_dir, self.filepath)\n        return model\n\n    def write(self, model: OscalBaseModel) -> bool:\n\"\"\"Write OSCAL model to repository.\"\"\"\n        logger.debug(f'Writing model {self.model_name}.')\n        model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        # split directory if the model was split\n        split_dir = pathlib.Path(self.model_dir, self.model_alias)\n\n        # Prepare actions; delete split model dir if any, recreate model file, and write to filepath\n        top_element = Element(model)\n        remove_action = RemovePathAction(split_dir)\n        create_action = CreatePathAction(self.filepath, True)\n        write_action = WriteFileAction(self.filepath, top_element, self.file_content_type)\n\n        # create a plan to create the directory and imported file.\n        import_plan = Plan()\n        import_plan.add_action(remove_action)\n        import_plan.add_action(create_action)\n        import_plan.add_action(write_action)\n\n        import_plan.execute()\n\n        logger.debug(f'Model {self.model_name} written to repository')\n        return True\n\n    def split(self, model_file: pathlib.Path, elements: List[str]) -> bool:\n\"\"\"Split the given OSCAL model file in repository.\n\n        Model file path should be relative to the main model directory, e.g., model dir is $TRESTLE_ROOT/catalogs/NIST\n        then model file path can be 'catalog/metadata.json' if metadata is to be split.\n\n        Elements should be specified relative to model file, e.g., 'metadata.props.*'\n        \"\"\"\n        logger.debug(f'Splitting model {self.model_name}, file {model_file}.')\n        # input model_file should be relative to the model dir\n        model_file_path = self.model_dir / model_file\n        model_file_path = model_file_path.resolve()\n        file_parent = model_file_path.parent\n        filename = model_file_path.name\n\n        elems = ''\n        first = True\n        for elem in elements:\n            if first:\n                elems = elem\n                first = False\n            else:\n                elems = elems + ',' + elem\n\n        success = False\n        try:\n            ret = splitcmd.SplitCmd().perform_split(file_parent, filename, elems, self.root_dir)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in splitting model: {e}')\n\n        logger.debug(f'Model {self.model_name}, file {model_file} splitted successfully.')\n        return success\n\n    def merge(self, elements: List[str], parent_model_dir: Optional[pathlib.Path] = None) -> bool:\n\"\"\"Merge OSCAL elements in repository.\n\n        The parent_model_dir specifies the parent model direcotry in which to merge relative to main model dir.\n        For example, if we have to merge 'metadata.*' into 'metadata' then parent_model_dir should be the 'catalog'\n        dir that contains the 'metadata.json' file or the 'metadata' directory\n        \"\"\"\n        logger.debug(f'Merging model {self.model_name}, parent dir {parent_model_dir}.')\n        if parent_model_dir is None:\n            effective_cwd = self.model_dir\n        else:\n            effective_cwd = self.model_dir / parent_model_dir\n\n        success = True\n        try:\n            for elem in elements:\n                plan = mergecmd.MergeCmd.merge(effective_cwd, ElementPath(elem), self.root_dir)\n                plan.execute()\n\n        except Exception as e:\n            raise TrestleError(f'Error in merging model: {e}')\n\n        logger.debug(f'Model {self.model_name} merged successfully.')\n        return success\n\n    def validate(self) -> bool:\n\"\"\"Validate OSCAL model in repository.\"\"\"\n        logger.debug(f'Validating model {self.model_name}.')\n        repo = Repository(self.root_dir)\n        success = repo.validate_model(self.model_type, self.model_name)\n        return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.__init__","title":"__init__(self, root_dir, model_type, name) special","text":"

                                                                            Initialize repository OSCAL model object.

                                                                            Source code in trestle/core/repository.py
                                                                            def __init__(self, root_dir: pathlib.Path, model_type: Type[OscalBaseModel], name: str) -> None:\n\"\"\"Initialize repository OSCAL model object.\"\"\"\n    if not file_utils.is_valid_project_root(root_dir):\n        raise TrestleError(f'Provided root directory {str(root_dir)} is not a valid Trestle root directory.')\n    self.root_dir = root_dir\n    self.model_type = model_type\n    self.model_name = name\n\n    # set model alais and dir\n    self.model_alias = classname_to_alias(self.model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(self.model_alias) is None:\n        raise TrestleError(f'Given model {self.model_alias} is not a top level model.')\n\n    plural_path = ModelUtils.model_type_to_model_dir(self.model_alias)\n    self.model_dir = self.root_dir / plural_path / self.model_name\n\n    if not self.model_dir.exists() or not self.model_dir.is_dir():\n        raise TrestleError(f'Model dir {self.model_name} does not exist.')\n\n    file_content_type = FileContentType.path_to_content_type(self.model_dir / self.model_alias)\n    if file_content_type == FileContentType.UNKNOWN:\n        raise TrestleError(f'Model file for model {self.model_name} does not exist.')\n    self.file_content_type = file_content_type\n\n    filepath = pathlib.Path(\n        self.model_dir,\n        self.model_alias + FileContentType.path_to_file_extension(self.model_dir / self.model_alias)\n    )\n\n    self.filepath = filepath\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.merge","title":"merge(self, elements, parent_model_dir=None)","text":"

                                                                            Merge OSCAL elements in repository.

                                                                            The parent_model_dir specifies the parent model direcotry in which to merge relative to main model dir. For example, if we have to merge 'metadata.*' into 'metadata' then parent_model_dir should be the 'catalog' dir that contains the 'metadata.json' file or the 'metadata' directory

                                                                            Source code in trestle/core/repository.py
                                                                            def merge(self, elements: List[str], parent_model_dir: Optional[pathlib.Path] = None) -> bool:\n\"\"\"Merge OSCAL elements in repository.\n\n    The parent_model_dir specifies the parent model direcotry in which to merge relative to main model dir.\n    For example, if we have to merge 'metadata.*' into 'metadata' then parent_model_dir should be the 'catalog'\n    dir that contains the 'metadata.json' file or the 'metadata' directory\n    \"\"\"\n    logger.debug(f'Merging model {self.model_name}, parent dir {parent_model_dir}.')\n    if parent_model_dir is None:\n        effective_cwd = self.model_dir\n    else:\n        effective_cwd = self.model_dir / parent_model_dir\n\n    success = True\n    try:\n        for elem in elements:\n            plan = mergecmd.MergeCmd.merge(effective_cwd, ElementPath(elem), self.root_dir)\n            plan.execute()\n\n    except Exception as e:\n        raise TrestleError(f'Error in merging model: {e}')\n\n    logger.debug(f'Model {self.model_name} merged successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.read","title":"read(self)","text":"

                                                                            Read OSCAL model from repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def read(self) -> OscalBaseModel:\n\"\"\"Read OSCAL model from repository.\"\"\"\n    logger.debug(f'Reading model {self.model_name}.')\n    model = load_validate_model_path(self.root_dir, self.filepath)\n    return model\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.split","title":"split(self, model_file, elements)","text":"

                                                                            Split the given OSCAL model file in repository.

                                                                            Model file path should be relative to the main model directory, e.g., model dir is $TRESTLE_ROOT/catalogs/NIST then model file path can be 'catalog/metadata.json' if metadata is to be split.

                                                                            Elements should be specified relative to model file, e.g., 'metadata.props.*'

                                                                            Source code in trestle/core/repository.py
                                                                            def split(self, model_file: pathlib.Path, elements: List[str]) -> bool:\n\"\"\"Split the given OSCAL model file in repository.\n\n    Model file path should be relative to the main model directory, e.g., model dir is $TRESTLE_ROOT/catalogs/NIST\n    then model file path can be 'catalog/metadata.json' if metadata is to be split.\n\n    Elements should be specified relative to model file, e.g., 'metadata.props.*'\n    \"\"\"\n    logger.debug(f'Splitting model {self.model_name}, file {model_file}.')\n    # input model_file should be relative to the model dir\n    model_file_path = self.model_dir / model_file\n    model_file_path = model_file_path.resolve()\n    file_parent = model_file_path.parent\n    filename = model_file_path.name\n\n    elems = ''\n    first = True\n    for elem in elements:\n        if first:\n            elems = elem\n            first = False\n        else:\n            elems = elems + ',' + elem\n\n    success = False\n    try:\n        ret = splitcmd.SplitCmd().perform_split(file_parent, filename, elems, self.root_dir)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in splitting model: {e}')\n\n    logger.debug(f'Model {self.model_name}, file {model_file} splitted successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.validate","title":"validate(self)","text":"

                                                                            Validate OSCAL model in repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def validate(self) -> bool:\n\"\"\"Validate OSCAL model in repository.\"\"\"\n    logger.debug(f'Validating model {self.model_name}.')\n    repo = Repository(self.root_dir)\n    success = repo.validate_model(self.model_type, self.model_name)\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.ManagedOSCAL.write","title":"write(self, model)","text":"

                                                                            Write OSCAL model to repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def write(self, model: OscalBaseModel) -> bool:\n\"\"\"Write OSCAL model to repository.\"\"\"\n    logger.debug(f'Writing model {self.model_name}.')\n    model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    # split directory if the model was split\n    split_dir = pathlib.Path(self.model_dir, self.model_alias)\n\n    # Prepare actions; delete split model dir if any, recreate model file, and write to filepath\n    top_element = Element(model)\n    remove_action = RemovePathAction(split_dir)\n    create_action = CreatePathAction(self.filepath, True)\n    write_action = WriteFileAction(self.filepath, top_element, self.file_content_type)\n\n    # create a plan to create the directory and imported file.\n    import_plan = Plan()\n    import_plan.add_action(remove_action)\n    import_plan.add_action(create_action)\n    import_plan.add_action(write_action)\n\n    import_plan.execute()\n\n    logger.debug(f'Model {self.model_name} written to repository')\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository","title":" Repository ","text":"

                                                                            Repository class for performing operations on Trestle repository.

                                                                            This class provides a set of APIs to perform operations on trestle repository programmatically rather than using the command line. It takes the trestle root directory as input while creating an instance of this object. Operations such as import and get model return a ManagedOSCAL object representing the specific model that can be used to perform operations on the specific models.

                                                                            Source code in trestle/core/repository.py
                                                                            class Repository:\n\"\"\"Repository class for performing operations on Trestle repository.\n\n    This class provides a set of APIs to perform operations on trestle repository programmatically\n    rather than using the command line. It takes the trestle root directory as input while creating\n    an instance of this object. Operations such as import and get model return a ManagedOSCAL object\n    representing the specific model that can be used to perform operations on the specific models.\n\n    \"\"\"\n\n    def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n        if not file_utils.is_valid_project_root(root_dir):\n            raise TrestleError(f'Provided root directory {root_dir} is not a valid Trestle root directory.')\n        self.root_dir = root_dir\n\n    def import_model(\n        self, model: OscalBaseModel, name: str, content_type: FileContentType = FileContentType.JSON\n    ) -> ManagedOSCAL:\n\"\"\"Import OSCAL object into trestle repository.\"\"\"\n        logger.debug(f'Importing model {name} of type {model.__class__.__name__}.')\n        model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        # Work out output directory and file\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n        desired_model_dir = self.root_dir / plural_path\n        desired_model_path = desired_model_dir / name / (model_alias + FileContentType.to_file_extension(content_type))\n        desired_model_path = desired_model_path.resolve()\n\n        if desired_model_path.exists():\n            raise TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n        content_type = FileContentType.to_content_type(pathlib.Path(desired_model_path).suffix)\n\n        # Prepare actions\n        top_element = Element(model)\n        create_action = CreatePathAction(desired_model_path, True)\n        write_action = WriteFileAction(desired_model_path, top_element, content_type)\n\n        # create a plan to create the directory and imported file.\n        import_plan = Plan()\n        import_plan.add_action(create_action)\n        import_plan.add_action(write_action)\n        import_plan.execute()\n\n        # Validate the imported file, rollback if unsuccessful\n        success = False\n        errmsg = ''\n        try:\n            success = self.validate_model(model.__class__, name)\n            if not success:\n                errmsg = f'Validation of model {name} did not pass'\n                logger.error(errmsg)\n        except Exception as err:\n            logger.error(errmsg)\n            errmsg = f'Import of model {name} failed. Validation failed with error: {err}'\n\n        if not success:\n            # rollback in case of validation error or failure\n            logger.debug(f'Rolling back import of model {name} to {desired_model_path}')\n            try:\n                import_plan.rollback()\n            except TrestleError as err:\n                logger.error(f'Failed to rollback: {err}. Remove {desired_model_path} to resolve state.')\n            else:\n                logger.debug(f'Successful rollback of import to {desired_model_path}')\n\n            # raise trestle error\n            raise TrestleError(errmsg)\n\n        # all well; model was imported and validated successfully\n        logger.debug(f'Model {name} of type {model.__class__.__name__} imported successfully.')\n        return ManagedOSCAL(self.root_dir, model.__class__, name)\n\n    def load_and_import_model(\n        self,\n        model_path: pathlib.Path,\n        name: str,\n        content_type: FileContentType = FileContentType.JSON\n    ) -> ManagedOSCAL:\n\"\"\"Load the model at the specified path into trestle with the specified name.\"\"\"\n        fetcher = cache.FetcherFactory.get_fetcher(self.root_dir, str(model_path))\n        model, _ = fetcher.get_oscal(True)\n\n        return self.import_model(model, name, content_type)\n\n    def list_models(self, model_type: Type[OscalBaseModel]) -> List[str]:\n\"\"\"List models of a given type in trestle repository.\"\"\"\n        logger.debug(f'Listing models of type {model_type.__name__}.')\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n        models = ModelUtils.get_models_of_type(model_alias, self.root_dir)\n\n        return models\n\n    def get_model(self, model_type: Type[OscalBaseModel], name: str) -> ManagedOSCAL:\n\"\"\"Get a specific OSCAL model from repository.\"\"\"\n        logger.debug(f'Getting model {name} of type {model_type.__name__}.')\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n        desired_model_dir = self.root_dir / plural_path / name\n\n        if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n            raise TrestleError(f'Model {name} does not exist.')\n\n        return ManagedOSCAL(self.root_dir, model_type, name)\n\n    def delete_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Delete an OSCAL model from repository.\"\"\"\n        logger.debug(f'Deleting model {name} of type {model_type.__name__}.')\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n        plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n        desired_model_dir = self.root_dir / plural_path / name\n\n        if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n            raise TrestleError(f'Model {name} does not exist.')\n        shutil.rmtree(desired_model_dir)\n\n        # remove model from dist directory if it exists\n        dist_model_dir = self.root_dir / const.TRESTLE_DIST_DIR / plural_path\n        file_content_type = FileContentType.path_to_content_type(dist_model_dir / name)\n        if file_content_type != FileContentType.UNKNOWN:\n            file_path = pathlib.Path(\n                dist_model_dir, name + FileContentType.path_to_file_extension(dist_model_dir / name)\n            )\n            logger.debug(f'Deleting model {name} from dist directory.')\n            os.remove(file_path)\n\n        logger.debug(f'Model {name} deleted successfully.')\n        return True\n\n    def assemble_model(self, model_type: Type[OscalBaseModel], name: str, extension: str = 'json') -> bool:\n\"\"\"Assemble an OSCAL model in repository and publish it to 'dist' directory.\"\"\"\n        logger.debug(f'Assembling model {name} of type {model_type.__name__}.')\n        success = False\n\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(\n            type=model_alias, name=name, extension=extension, trestle_root=self.root_dir, verbose=verbose\n        )\n\n        try:\n            ret = assemblecmd.AssembleCmd().assemble_model(model_alias, args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in assembling model: {e}')\n\n        logger.debug(f'Model {name} assembled successfully.')\n        return success\n\n    def validate_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Validate an OSCAL model in repository.\"\"\"\n        logger.debug(f'Validating model {name} of type {model_type.__name__}.')\n        success = False\n\n        model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n        if parser.to_full_model_name(model_alias) is None:\n            raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n        verbose = log.get_current_verbosity_level(logger)\n        args = argparse.Namespace(type=model_alias, name=name, trestle_root=self.root_dir, verbose=verbose, quiet=False)\n\n        try:\n            ret = validatecmd.ValidateCmd()._run(args)\n            if ret == 0:\n                success = True\n        except Exception as e:\n            raise TrestleError(f'Error in validating model: {e}')\n\n        logger.debug(f'Model {name} validated successfully.')\n        return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.__init__","title":"__init__(self, root_dir) special","text":"

                                                                            Initialize trestle repository object.

                                                                            Source code in trestle/core/repository.py
                                                                            def __init__(self, root_dir: pathlib.Path) -> None:\n\"\"\"Initialize trestle repository object.\"\"\"\n    if not file_utils.is_valid_project_root(root_dir):\n        raise TrestleError(f'Provided root directory {root_dir} is not a valid Trestle root directory.')\n    self.root_dir = root_dir\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.assemble_model","title":"assemble_model(self, model_type, name, extension='json')","text":"

                                                                            Assemble an OSCAL model in repository and publish it to 'dist' directory.

                                                                            Source code in trestle/core/repository.py
                                                                            def assemble_model(self, model_type: Type[OscalBaseModel], name: str, extension: str = 'json') -> bool:\n\"\"\"Assemble an OSCAL model in repository and publish it to 'dist' directory.\"\"\"\n    logger.debug(f'Assembling model {name} of type {model_type.__name__}.')\n    success = False\n\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(\n        type=model_alias, name=name, extension=extension, trestle_root=self.root_dir, verbose=verbose\n    )\n\n    try:\n        ret = assemblecmd.AssembleCmd().assemble_model(model_alias, args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in assembling model: {e}')\n\n    logger.debug(f'Model {name} assembled successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.delete_model","title":"delete_model(self, model_type, name)","text":"

                                                                            Delete an OSCAL model from repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def delete_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Delete an OSCAL model from repository.\"\"\"\n    logger.debug(f'Deleting model {name} of type {model_type.__name__}.')\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n    desired_model_dir = self.root_dir / plural_path / name\n\n    if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n        raise TrestleError(f'Model {name} does not exist.')\n    shutil.rmtree(desired_model_dir)\n\n    # remove model from dist directory if it exists\n    dist_model_dir = self.root_dir / const.TRESTLE_DIST_DIR / plural_path\n    file_content_type = FileContentType.path_to_content_type(dist_model_dir / name)\n    if file_content_type != FileContentType.UNKNOWN:\n        file_path = pathlib.Path(\n            dist_model_dir, name + FileContentType.path_to_file_extension(dist_model_dir / name)\n        )\n        logger.debug(f'Deleting model {name} from dist directory.')\n        os.remove(file_path)\n\n    logger.debug(f'Model {name} deleted successfully.')\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.get_model","title":"get_model(self, model_type, name)","text":"

                                                                            Get a specific OSCAL model from repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def get_model(self, model_type: Type[OscalBaseModel], name: str) -> ManagedOSCAL:\n\"\"\"Get a specific OSCAL model from repository.\"\"\"\n    logger.debug(f'Getting model {name} of type {model_type.__name__}.')\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n    desired_model_dir = self.root_dir / plural_path / name\n\n    if not desired_model_dir.exists() or not desired_model_dir.is_dir():\n        raise TrestleError(f'Model {name} does not exist.')\n\n    return ManagedOSCAL(self.root_dir, model_type, name)\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.import_model","title":"import_model(self, model, name, content_type=<FileContentType.JSON: 1>)","text":"

                                                                            Import OSCAL object into trestle repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def import_model(\n    self, model: OscalBaseModel, name: str, content_type: FileContentType = FileContentType.JSON\n) -> ManagedOSCAL:\n\"\"\"Import OSCAL object into trestle repository.\"\"\"\n    logger.debug(f'Importing model {name} of type {model.__class__.__name__}.')\n    model_alias = classname_to_alias(model.__class__.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    # Work out output directory and file\n    plural_path = ModelUtils.model_type_to_model_dir(model_alias)\n\n    desired_model_dir = self.root_dir / plural_path\n    desired_model_path = desired_model_dir / name / (model_alias + FileContentType.to_file_extension(content_type))\n    desired_model_path = desired_model_path.resolve()\n\n    if desired_model_path.exists():\n        raise TrestleError(f'OSCAL file to be created here: {desired_model_path} exists.')\n\n    content_type = FileContentType.to_content_type(pathlib.Path(desired_model_path).suffix)\n\n    # Prepare actions\n    top_element = Element(model)\n    create_action = CreatePathAction(desired_model_path, True)\n    write_action = WriteFileAction(desired_model_path, top_element, content_type)\n\n    # create a plan to create the directory and imported file.\n    import_plan = Plan()\n    import_plan.add_action(create_action)\n    import_plan.add_action(write_action)\n    import_plan.execute()\n\n    # Validate the imported file, rollback if unsuccessful\n    success = False\n    errmsg = ''\n    try:\n        success = self.validate_model(model.__class__, name)\n        if not success:\n            errmsg = f'Validation of model {name} did not pass'\n            logger.error(errmsg)\n    except Exception as err:\n        logger.error(errmsg)\n        errmsg = f'Import of model {name} failed. Validation failed with error: {err}'\n\n    if not success:\n        # rollback in case of validation error or failure\n        logger.debug(f'Rolling back import of model {name} to {desired_model_path}')\n        try:\n            import_plan.rollback()\n        except TrestleError as err:\n            logger.error(f'Failed to rollback: {err}. Remove {desired_model_path} to resolve state.')\n        else:\n            logger.debug(f'Successful rollback of import to {desired_model_path}')\n\n        # raise trestle error\n        raise TrestleError(errmsg)\n\n    # all well; model was imported and validated successfully\n    logger.debug(f'Model {name} of type {model.__class__.__name__} imported successfully.')\n    return ManagedOSCAL(self.root_dir, model.__class__, name)\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.list_models","title":"list_models(self, model_type)","text":"

                                                                            List models of a given type in trestle repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def list_models(self, model_type: Type[OscalBaseModel]) -> List[str]:\n\"\"\"List models of a given type in trestle repository.\"\"\"\n    logger.debug(f'Listing models of type {model_type.__name__}.')\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n    models = ModelUtils.get_models_of_type(model_alias, self.root_dir)\n\n    return models\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.load_and_import_model","title":"load_and_import_model(self, model_path, name, content_type=<FileContentType.JSON: 1>)","text":"

                                                                            Load the model at the specified path into trestle with the specified name.

                                                                            Source code in trestle/core/repository.py
                                                                            def load_and_import_model(\n    self,\n    model_path: pathlib.Path,\n    name: str,\n    content_type: FileContentType = FileContentType.JSON\n) -> ManagedOSCAL:\n\"\"\"Load the model at the specified path into trestle with the specified name.\"\"\"\n    fetcher = cache.FetcherFactory.get_fetcher(self.root_dir, str(model_path))\n    model, _ = fetcher.get_oscal(True)\n\n    return self.import_model(model, name, content_type)\n
                                                                            "},{"location":"api_reference/trestle.core.repository/#trestle.core.repository.Repository.validate_model","title":"validate_model(self, model_type, name)","text":"

                                                                            Validate an OSCAL model in repository.

                                                                            Source code in trestle/core/repository.py
                                                                            def validate_model(self, model_type: Type[OscalBaseModel], name: str) -> bool:\n\"\"\"Validate an OSCAL model in repository.\"\"\"\n    logger.debug(f'Validating model {name} of type {model_type.__name__}.')\n    success = False\n\n    model_alias = classname_to_alias(model_type.__name__, AliasMode.JSON)\n    if parser.to_full_model_name(model_alias) is None:\n        raise TrestleError(f'Given model {model_alias} is not a top level model.')\n\n    verbose = log.get_current_verbosity_level(logger)\n    args = argparse.Namespace(type=model_alias, name=name, trestle_root=self.root_dir, verbose=verbose, quiet=False)\n\n    try:\n        ret = validatecmd.ValidateCmd()._run(args)\n        if ret == 0:\n            success = True\n    except Exception as e:\n        raise TrestleError(f'Error in validating model: {e}')\n\n    logger.debug(f'Model {name} validated successfully.')\n    return success\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.merge/","title":"merge","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge","title":"trestle.core.resolver.merge","text":"

                                                                            Create resolved catalog from profile.

                                                                            "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.CATALOG_EXCLUDE","title":"CATALOG_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.CONTROL_EXCLUDE","title":"CONTROL_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.ID","title":"ID","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.ITEM_EXCLUDE_MAP","title":"ITEM_EXCLUDE_MAP","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.NAME","title":"NAME","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.PARAMETER_EXCLUDE","title":"PARAMETER_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.PART_EXCLUDE","title":"PART_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.PROPERTY_EXCLUDE","title":"PROPERTY_EXCLUDE","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge","title":" Merge (Filter) ","text":"

                                                                            Merge the incoming catalogs according to rules in the profile.

                                                                            The incoming catalogs have already been pruned based on the import. Now the controls must be gathered, merged, and grouped based on the merge settings.

                                                                            Source code in trestle/core/resolver/merge.py
                                                                            class Merge(Pipeline.Filter):\n\"\"\"\n    Merge the incoming catalogs according to rules in the profile.\n\n    The incoming catalogs have already been pruned based on the import.\n    Now the controls must be gathered, merged, and grouped based on the merge settings.\n    \"\"\"\n\n    def __init__(self, profile: prof.Profile) -> None:\n\"\"\"Initialize the class with the profile.\"\"\"\n        logger.debug('merge filter initialize')\n        self._profile = profile\n\n    def _get_id(self, item: OBT) -> Optional[str]:\n        id_ = getattr(item, ID, None)\n        if id_ is None:\n            id_ = getattr(item, NAME, None)\n        return id_\n\n    def _item_genertor(self, dest: List[OBT], src: List[OBT], merge_method: Optional[str]) -> Iterator[OBT]:\n        if merge_method == prof.CombinationMethodValidValues.keep.value:\n            dest.extend(src)\n        else:\n            for item in src:\n                # if there is an exact copy of this in dest then ignore it\n                if item not in dest:\n                    yield item\n\n    def _merge_item(self, item: OBT, dest: List[OBT], merge_method: Optional[str]) -> bool:\n        merged = False\n        item_id = self._get_id(item)\n        if item_id is not None:\n            for other in dest:\n                other_id = self._get_id(other)\n                if other_id != item_id:\n                    continue\n                if merge_method == prof.CombinationMethodValidValues.merge.value:\n                    self._merge_items(other, item, merge_method)\n                merged = True\n                break\n        return merged\n\n    def _merge_lists(self, dest: List[OBT], src: List[OBT], merge_method: Optional[str]) -> None:\n        added_items = []\n        if merge_method == prof.CombinationMethodValidValues.keep.value:\n            dest.extend(src)\n            return\n        for item in self._item_genertor(dest, src, merge_method):\n            merged = self._merge_item(item, dest, merge_method)\n            # it isn't already in dest and no match was found for merge, so append\n            if not merged:\n                added_items.append(item)\n        dest.extend(added_items)\n\n    def _merge_attrs(\n        self, dest: Union[OBT, List[OBT]], src: Union[OBT, List[OBT]], attr: str, merge_method: Optional[str]\n    ) -> None:\n\"\"\"Merge this attr of src into the attr of dest.\"\"\"\n        src_attr = getattr(src, attr, None)\n        if src_attr is None:\n            return\n        item_type = type(src).__name__\n        if attr in ITEM_EXCLUDE_MAP.get(item_type, []):\n            return\n        dest_attr = getattr(dest, attr, None)\n        if dest_attr and isinstance(dest_attr, list):\n            self._merge_lists(dest_attr, src_attr, merge_method)\n            setattr(dest, attr, dest_attr)\n            return\n        if dest_attr and merge_method == prof.CombinationMethodValidValues.use_first.value:\n            return\n        if dest_attr == src_attr and merge_method not in [None, prof.CombinationMethodValidValues.keep.value]:\n            return\n        setattr(dest, attr, src_attr)\n\n    def _merge_items(self, dest: OBT, src: OBT, merge_method: Optional[str]) -> None:\n\"\"\"Merge two items recursively.\"\"\"\n        for field in src.__fields_set__:\n            self._merge_attrs(dest, src, field, merge_method)\n\n    def _group_contents(self, group: cat.Group) -> Tuple[List[cat.Control], List[com.Parameter]]:\n\"\"\"Get flattened content of group and its groups recursively.\"\"\"\n        controls = []\n        params = []\n        controls.extend(as_list(group.controls))\n        params.extend(as_list(group.params))\n        if group.groups is not None:\n            for sub_group in group.groups:\n                new_controls, new_params = self._group_contents(sub_group)\n                controls.extend(new_controls)\n                params.extend(new_params)\n        return controls, params\n\n    def _flatten_catalog(self, catalog: cat.Catalog, as_is: bool) -> cat.Catalog:\n\"\"\"Flatten the groups of the catalog if as_is is False.\"\"\"\n        if as_is or catalog.groups is None:\n            return catalog\n\n        # as_is is False so flatten the controls into a single list\n        catalog.controls = as_list(catalog.controls)\n        catalog.params = as_list(catalog.params)\n        for group in catalog.groups:\n            new_controls, new_params = self._group_contents(group)\n            catalog.controls.extend(new_controls)\n            catalog.params.extend(new_params)\n        catalog.controls = none_if_empty(catalog.controls)\n        catalog.params = none_if_empty(catalog.params)\n        catalog.groups = None\n        return catalog\n\n    def _merge_two_catalogs(\n        self, dest: cat.Catalog, src: cat.Catalog, merge_method: Optional[str], as_is: bool\n    ) -> cat.Catalog:\n        # merge_method is use_first, merge, keep\n        # no combine or merge_method equates to merge_method=keep\n        # if as_is is false, the result is flattened\n\n        dest = self._flatten_catalog(dest, as_is)\n        src = self._flatten_catalog(src, as_is)\n\n        self._merge_items(dest, src, merge_method)\n\n        return dest\n\n    def _merge_catalog(self, merged: Optional[cat.Catalog], catalog: cat.Catalog) -> cat.Catalog:\n\"\"\"Merge the controls in the catalog into merged catalog.\"\"\"\n        # no merge means keep, including dups\n        # same for merge with no combine\n        # groups are merged only if separate directive such as as-is is given\n        # use-first is a merge combination rule\n        # merge is a merge combination rule for controls.  groups are not merged by this rule\n        # merge/as-is and merge/custom are used for merging groups\n        # if neither as-is nor custom is specified - just get single list of controls\n        # unstructured controls should appear after any loose params\n\n        # make copies to avoid changing input objects\n        local_cat = catalog.copy(deep=True)\n        local_merged = merged.copy(deep=True) if merged else None\n\n        merge_method = prof.CombinationMethodValidValues.keep.value\n        as_is = False\n        if self._profile.merge is not None:\n            if self._profile.merge.custom is not None:\n                raise TrestleError('Profile with custom merge is not supported.')\n            if self._profile.merge.as_is is not None:\n                as_is = self._profile.merge.as_is\n            if self._profile.merge.combine is None:\n                logger.debug('Profile has merge but no combine so defaulting to combine/merge.')\n                merge_method = prof.CombinationMethodValidValues.merge.value\n            else:\n                merge_combine = self._profile.merge.combine\n                if merge_combine.method.value is None:\n                    logger.debug('Profile has merge combine but no method.  Defaulting to merge.')\n                    merge_method = prof.CombinationMethodValidValues.merge.value\n                else:\n                    merge_method = merge_combine.method.value\n\n        if local_merged is None:\n            return self._flatten_catalog(local_cat, as_is)\n\n        # merge the incoming catalog with merged based on merge_method and as_is\n        return self._merge_two_catalogs(local_merged, local_cat, merge_method, as_is)\n\n    def process(self, pipelines: List[Pipeline]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n        Merge the incoming catalogs.\n\n        This pulls from import and iterates over the incoming catalogs.\n        The way groups, lists of controls, and controls themselves get merged is specified by the profile.\n        \"\"\"\n        merged: Optional[cat.Catalog] = None\n        logger.debug(f'merge entering process with {len(pipelines)} pipelines')\n        for pipeline in pipelines:\n            catalog = next(pipeline.process(None))\n            merged = self._merge_catalog(merged, catalog)\n        yield merged  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge.__init__","title":"__init__(self, profile) special","text":"

                                                                            Initialize the class with the profile.

                                                                            Source code in trestle/core/resolver/merge.py
                                                                            def __init__(self, profile: prof.Profile) -> None:\n\"\"\"Initialize the class with the profile.\"\"\"\n    logger.debug('merge filter initialize')\n    self._profile = profile\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.merge/#trestle.core.resolver.merge.Merge.process","title":"process(self, pipelines)","text":"

                                                                            Merge the incoming catalogs.

                                                                            This pulls from import and iterates over the incoming catalogs. The way groups, lists of controls, and controls themselves get merged is specified by the profile.

                                                                            Source code in trestle/core/resolver/merge.py
                                                                            def process(self, pipelines: List[Pipeline]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n    Merge the incoming catalogs.\n\n    This pulls from import and iterates over the incoming catalogs.\n    The way groups, lists of controls, and controls themselves get merged is specified by the profile.\n    \"\"\"\n    merged: Optional[cat.Catalog] = None\n    logger.debug(f'merge entering process with {len(pipelines)} pipelines')\n    for pipeline in pipelines:\n        catalog = next(pipeline.process(None))\n        merged = self._merge_catalog(merged, catalog)\n    yield merged  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.modify/","title":"modify","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify","title":"trestle.core.resolver.modify","text":"

                                                                            Create resolved catalog from profile.

                                                                            "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify","title":" Modify (Filter) ","text":"

                                                                            Modify the controls based on the profile.

                                                                            Source code in trestle/core/resolver/modify.py
                                                                            class Modify(Pipeline.Filter):\n\"\"\"Modify the controls based on the profile.\"\"\"\n\n    def __init__(\n        self,\n        profile: prof.Profile,\n        change_prose: bool = False,\n        block_adds: bool = False,\n        block_params: bool = False,\n        params_format: str = None,\n        param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n        show_value_warnings: bool = False,\n        value_assigned_prefix: Optional[str] = None,\n        value_not_assigned_prefix: Optional[str] = None\n    ) -> None:\n\"\"\"Initialize the filter.\"\"\"\n        self._profile = profile\n        self._catalog_interface: Optional[CatalogInterface] = None\n        self._block_adds = block_adds\n        self._block_params = block_params\n        self._change_prose = change_prose\n        self._params_format = params_format\n        self._param_rep = param_rep\n        self.show_value_warnings = show_value_warnings\n        self._value_assigned_prefix = value_assigned_prefix\n        self._value_not_assigned_prefix = value_not_assigned_prefix\n        logger.debug(f'modify initialize filter with profile {profile.metadata.title}')\n\n    @staticmethod\n    def _add_adds_to_part(part: common.Part, add: prof.Add, added_parts=False) -> None:\n        for attr in ['params', 'props', 'parts', 'links']:\n            # don't add parts if already added earlier\n            if added_parts and attr == 'parts':\n                continue\n            add_list = getattr(add, attr, None)\n            if add_list:\n                Modify._add_attr_to_part(part, add_list[:], attr, add.position)\n\n    @staticmethod\n    def _add_to_list(parts_list: List[common.Part], add: prof.Add) -> bool:\n\"\"\"Add the contents of the add according to its by_id and position.\n\n        Return True on success or False if id needed and not found.\n\n        This is only called when by_id is not None.\n        The add will be inserted if the id is found, or return False if not.\n        This allows a separate recursive routine to search sub-lists for the id.\n        Position before/after will put the item adjacent to the target in the same list as target\n        Position starting/ending will put the item within the target itself\n        \"\"\"\n        # Test here for matched by_id attribute.\n        added_parts = False\n        for index in range(len(parts_list)):\n            # find the matching part\n            if parts_list[index].id == add.by_id:\n                if add.position == prof.PositionValidValues.after:\n                    for offset, new_item in enumerate(as_list(add.parts)):\n                        parts_list.insert(index + 1 + offset, new_item)\n                    added_parts = True\n                elif add.position == prof.PositionValidValues.before:\n                    for offset, new_item in enumerate(as_list(add.parts)):\n                        parts_list.insert(index + offset, new_item)\n                    added_parts = True\n                # if starting or ending or None, the adds go directly into this part according to type\n                Modify._add_adds_to_part(parts_list[index], add, added_parts)\n                return True\n        return False\n\n    @staticmethod\n    def _add_to_parts(parts: List[common.Part], add: prof.Add) -> bool:\n\"\"\"\n        Add the add to the parts.\n\n        This is only called if add.by_id is not None.\n        \"\"\"\n        if Modify._add_to_list(parts, add):\n            return True\n        for part in parts:\n            if part.parts is not None and Modify._add_to_parts(part.parts, add):\n                return True\n        return False\n\n    @staticmethod\n    def _add_attr_to_part(part: common.Part, items: List[OBT], attr: str, position: Optional[str]) -> None:\n        attr_list = as_list(getattr(part, attr, None))\n        # position may be None and if so will go at end\n        if position in [prof.PositionValidValues.starting, prof.PositionValidValues.before]:\n            items.extend(attr_list)\n            attr_list = items\n        else:\n            attr_list.extend(items)\n        setattr(part, attr, attr_list)\n\n    @staticmethod\n    def _add_attr_to_control(control: cat.Control, items: List[OBT], attr: str, position: Optional[str]) -> None:\n        attr_list = as_list(getattr(control, attr, None))\n        if position in [prof.PositionValidValues.starting, prof.PositionValidValues.before]:\n            items.extend(attr_list)\n            attr_list = items\n        else:\n            attr_list.extend(items)\n        setattr(control, attr, attr_list)\n\n    @staticmethod\n    def _add_to_trestle_props(control: cat.Control, add: prof.Add) -> None:\n\"\"\"Add props to special trestle part that keeps track of inherited props.\"\"\"\n        if add.props:\n            trestle_part = get_item_from_list(control.parts, TRESTLE_INHERITED_PROPS_TRACKER, lambda p: p.name)\n            if trestle_part is None:\n                trestle_part = common.Part(\n                    id=TRESTLE_INHERITED_PROPS_TRACKER, name=TRESTLE_INHERITED_PROPS_TRACKER, props=[], parts=[]\n                )\n                control.parts = as_list(control.parts)\n                control.parts.append(trestle_part)\n                trestle_part = control.parts[-1]\n            if add.by_id is None or add.by_id == control.id:\n                trestle_part.props.extend(add.props)\n            else:\n                by_id_part = get_item_from_list(trestle_part.parts, add.by_id, lambda p: p.title)\n                if by_id_part is None:\n                    trestle_part.parts.append(\n                        common.Part(name=TRESTLE_INHERITED_PROPS_TRACKER + '_' + add.by_id, title=add.by_id, props=[])\n                    )\n                    by_id_part = trestle_part.parts[-1]\n                by_id_part.props.extend(add.props)\n\n    @staticmethod\n    def _add_to_control(control: cat.Control, add: prof.Add) -> None:\n\"\"\"First step in applying Add to control.\"\"\"\n        control.parts = as_list(control.parts)\n        if add.by_id is None or add.by_id == control.id:\n            # add contents will be added to the control directly and with no recursion\n            for attr in ['params', 'props', 'parts', 'links']:\n                add_list = getattr(add, attr, None)\n                if add_list:\n                    Modify._add_attr_to_control(control, add_list[:], attr, add.position)\n        else:\n            # this is only called if by_id is not None\n            if not Modify._add_to_parts(control.parts, add):\n                logger.warning(f'Could not find id for add in control {control.id}: {add.by_id}')\n        Modify._add_to_trestle_props(control, add)\n        control.parts = none_if_empty(control.parts)\n\n    @staticmethod\n    def _set_overwrite_items(param: common.Parameter, set_param: prof.SetParameter) -> None:\n        # these overwrite\n        if set_param.class_:\n            param.class_ = set_param.class_\n        if set_param.depends_on:\n            param.depends_on = set_param.depends_on\n        if set_param.label:\n            param.label = set_param.label\n        if set_param.usage:\n            param.usage = set_param.usage\n        if set_param.values:\n            param.values = set_param.values\n        if set_param.select:\n            param.select = set_param.select\n\n    @staticmethod\n    def _set_appended_items(param: common.Parameter, set_param: prof.SetParameter) -> None:\n        # these append\n        if set_param.constraints:\n            if not param.constraints:\n                param.constraints = []\n            param.constraints.extend(set_param.constraints)\n        if set_param.guidelines:\n            if not param.guidelines:\n                param.guidelines = []\n            param.guidelines.extend(set_param.guidelines)\n\n    @staticmethod\n    def _set_replaced_or_appended_items(param: common.Parameter, set_param: prof.SetParameter) -> None:\n        # these replace or append\n        if set_param.props:\n            new_props = as_list(param.props)\n            names = [prop.name for prop in new_props]\n            for prop in set_param.props:\n                if prop.name in names:\n                    new_props[names.index(prop.name)] = prop\n                else:\n                    new_props.append(prop)\n            param.props = new_props\n        if set_param.links:\n            new_links = as_list(param.links)\n            hrefs = [link.href for link in new_links]\n            for link in set_param.links:\n                if link.href in hrefs:\n                    new_links[hrefs.index(link.href)] = link\n                else:\n                    new_links.append(link)\n            param.links = new_links\n\n    def _set_parameter_in_control_or_loose(self, set_param: prof.SetParameter) -> None:\n\"\"\"\n        Find the control with the param_id in it and set the parameter contents.\n\n        It modifies controls in the control_dict not the catalog.\n        Parameters are either bound to a control or are 'loose' and bound to the catalog itself.\n        \"\"\"\n        # find the target param in control or the catalog's loose ones, i.e. catalog.params\n        control = self._catalog_interface.get_control_by_param_id(set_param.param_id)\n        loose_param = False\n        if control:\n            control.params = as_list(control.params)\n            param_ids = [param.id for param in control.params]\n            if set_param.param_id not in param_ids:\n                raise TrestleNotFoundError(f'Param id {set_param.param_id} not found in control {control.id}')\n            index = param_ids.index(set_param.param_id)\n            param = control.params[index]\n        else:\n            param = self._catalog_interface.loose_param_dict.get(set_param.param_id, None)\n            if param:\n                loose_param = True\n            else:\n                logger.warning(f'SetParameter for param_id {set_param.param_id} not found in catalog')\n                return\n\n        # rules here follow https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/\n        # see 'Modify Phase' and Setting Parameters\n\n        Modify._set_overwrite_items(param, set_param)\n        Modify._set_appended_items(param, set_param)\n        Modify._set_replaced_or_appended_items(param, set_param)\n\n        if loose_param:\n            self._catalog_interface.loose_param_dict[set_param.param_id] = param\n        else:\n            control.params[index] = param\n            self._catalog_interface.replace_control(control)\n\n    def _modify_controls(self, catalog: cat.Catalog) -> cat.Catalog:\n\"\"\"Modify the controls based on the profile.\"\"\"\n        logger.debug(f'modify specify catalog {catalog.metadata.title} for profile {self._profile.metadata.title}')\n        self._catalog_interface = CatalogInterface(catalog)\n        alters: Optional[List[prof.Alter]] = None\n        # find the modify and alters\n        if self._profile.modify:\n            # change all parameter values\n            if self._profile.modify.set_parameters and not self._block_params:\n                set_param_list = self._profile.modify.set_parameters\n                for set_param in set_param_list:\n                    self._set_parameter_in_control_or_loose(set_param)\n            alters = self._profile.modify.alters\n\n        # an add with no by-id applies to the control\n        # if position is starting it should appear immediately after title\n        # if position is ending it should appear at end\n        # if not specified it defaults to ending\n        # if no by-id then before is treated as starting and after is treated as ending\n        if alters is not None:\n            title = self._profile.metadata.title\n            for alter in alters:\n                if alter.control_id is None:\n                    logger.warning(f'Alter must have control id specified in profile {title}.')\n                    continue\n                id_ = alter.control_id\n                if alter.removes is not None:\n                    logger.warning(f'Alter not supported for removes in profile {title} control {id_}')\n                    continue\n                # we want a warning about adds even if adds are blocked, as in profile generate\n                if alter.adds is None:\n                    logger.warning(f'Alter has no adds in profile {title} control {id_}')\n                    continue\n                if not self._block_adds:\n                    for add in alter.adds:\n                        control = self._catalog_interface.get_control(id_)\n                        if control is None:\n                            logger.warning(\n                                f'Alter/Add refers to control {id_} but it is not found in the import '\n                                + f'for profile {self._profile.metadata.title}'\n                            )\n                        else:\n                            self._add_to_control(control, add)\n                            self._catalog_interface.replace_control(control)\n\n        if self._change_prose:\n            # go through all controls and fix the prose based on param values\n            self._catalog_interface._change_prose_with_param_values(\n                self._params_format,\n                self._param_rep,\n                self.show_value_warnings,\n                self._value_assigned_prefix,\n                self._value_not_assigned_prefix\n            )\n\n        catalog = self._catalog_interface.get_catalog()\n\n        # update the original profile metadata with new contents\n        # roles and responsible-parties will be pulled in with new uuid's\n        # the title simply becomes the title of the current profile - and will get overwritten\n        # by any other profiles downstream so that only the final profile title is used\n        new_metadata = self._profile.metadata\n        new_metadata.title = self._profile.metadata.title\n        new_metadata.oscal_version = OSCAL_VERSION\n\n        links: List[common.Link] = []\n        for import_ in self._profile.imports:\n            links.append(common.Link(**{'href': import_.href, 'rel': RESOLUTION_SOURCE}))\n        new_metadata.links = links\n\n        # move catalog controls from dummy group '' into the catalog\n        for group in as_list(catalog.groups):\n            if not group.id:\n                catalog.controls = group.controls\n                catalog.groups.remove(group)\n                break\n\n        catalog.metadata = new_metadata\n\n        return catalog\n\n    def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:\n\"\"\"Make the modifications to the controls based on the profile.\"\"\"\n        catalog = next(catalog_iter)\n        logger.debug(\n            f'modify process with catalog {catalog.metadata.title} using profile {self._profile.metadata.title}'\n        )\n        yield self._modify_controls(catalog)\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify.__init__","title":"__init__(self, profile, change_prose=False, block_adds=False, block_params=False, params_format=None, param_rep=<ParameterRep.LEAVE_MOUSTACHE: 0>, show_value_warnings=False, value_assigned_prefix=None, value_not_assigned_prefix=None) special","text":"

                                                                            Initialize the filter.

                                                                            Source code in trestle/core/resolver/modify.py
                                                                            def __init__(\n    self,\n    profile: prof.Profile,\n    change_prose: bool = False,\n    block_adds: bool = False,\n    block_params: bool = False,\n    params_format: str = None,\n    param_rep: ParameterRep = ParameterRep.LEAVE_MOUSTACHE,\n    show_value_warnings: bool = False,\n    value_assigned_prefix: Optional[str] = None,\n    value_not_assigned_prefix: Optional[str] = None\n) -> None:\n\"\"\"Initialize the filter.\"\"\"\n    self._profile = profile\n    self._catalog_interface: Optional[CatalogInterface] = None\n    self._block_adds = block_adds\n    self._block_params = block_params\n    self._change_prose = change_prose\n    self._params_format = params_format\n    self._param_rep = param_rep\n    self.show_value_warnings = show_value_warnings\n    self._value_assigned_prefix = value_assigned_prefix\n    self._value_not_assigned_prefix = value_not_assigned_prefix\n    logger.debug(f'modify initialize filter with profile {profile.metadata.title}')\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.modify/#trestle.core.resolver.modify.Modify.process","title":"process(self, catalog_iter)","text":"

                                                                            Make the modifications to the controls based on the profile.

                                                                            Source code in trestle/core/resolver/modify.py
                                                                            def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:\n\"\"\"Make the modifications to the controls based on the profile.\"\"\"\n    catalog = next(catalog_iter)\n    logger.debug(\n        f'modify process with catalog {catalog.metadata.title} using profile {self._profile.metadata.title}'\n    )\n    yield self._modify_controls(catalog)\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.prune/","title":"prune","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune","title":"trestle.core.resolver.prune","text":"

                                                                            Create resolved catalog from profile.

                                                                            "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune","title":" Prune (Filter) ","text":"

                                                                            Prune the catalog based on the import include rule.

                                                                            Source code in trestle/core/resolver/prune.py
                                                                            class Prune(Pipeline.Filter):\n\"\"\"Prune the catalog based on the import include rule.\"\"\"\n\n    def __init__(self, import_: prof.Import, profile: prof.Profile) -> None:\n\"\"\"\n        Inject the import.\n\n        This needs to be created prior to knowing the catalog.\n        The profile itself is only needed for debug messages.\n        The import is one possibly several imports in that profile.\n        \"\"\"\n        self._import = import_\n        self._profile = profile\n        self._catalog_interface: Optional[CatalogInterface] = None\n        self._catalog: Optional[cat.Catalog] = None\n\n    def _set_catalog(self, catalog: cat.Catalog) -> None:\n\"\"\"Set the catalog used by the catalog interface.\"\"\"\n        self._catalog_interface = CatalogInterface(catalog)\n        self._catalog = catalog\n\n    def _controls_selected(self, select_list: Optional[List[prof.SelectControl]]) -> List[str]:\n        control_ids: List[str] = []\n        if select_list is not None:\n            for select_control in select_list:\n                if select_control.matching is not None:\n                    raise TrestleError('Profiles with SelectControl based on matching are not supported.')\n                include_children = select_control.with_child_controls == 'yes'\n                if select_control.with_ids:\n                    new_ids = select_control.with_ids\n                    for withid_ in new_ids:\n                        id_ = withid_.__root__\n                        control_ids.append(id_)\n                        if include_children:\n                            control_ids.extend(self._catalog_interface.get_dependent_control_ids(id_))\n        return control_ids\n\n    def _find_needed_control_ids(self) -> List[str]:\n\"\"\"Get list of control_ids needed by profile and corresponding groups.\"\"\"\n        if self._import.include_controls is not None:\n            include_ids = self._controls_selected(self._import.include_controls)\n        else:\n            if self._import.include_all is None:\n                logger.warning('Profile does not specify include-controls, so including all.')\n            include_ids = self._catalog_interface.get_control_ids()\n\n        exclude_ids = self._controls_selected(self._import.exclude_controls)\n\n        if not set(include_ids).issuperset(set(exclude_ids)):\n            logger.debug(f'include_ids is not a superset of exclude_ids in import {self._import.href}')\n        return sorted([id_ for id_ in include_ids if id_ not in exclude_ids])\n\n    def _prune_control(self, needed_ids: List[str], control: cat.Control, exclude_ids: List[str]) -> cat.Control:\n\"\"\"\n        Prune the control based on the Import requirements.\n\n        This is only called if the control is needed\n        Some or all of its sub_controls may not be needed\n        This always returns the original control, possibly with fewer subcontrols\n        \"\"\"\n        if control.controls is None:\n            return control\n        controls = []\n        for sub_control in control.controls:\n            if sub_control.id in needed_ids and sub_control.id not in exclude_ids:\n                controls.append(self._prune_control(needed_ids, sub_control, exclude_ids))\n                exclude_ids.append(sub_control.id)\n        control.controls = none_if_empty(controls)\n        return control\n\n    def _prune_controls(self, needed_ids: List[str]) -> List[str]:\n        loaded_ids: List[str] = []\n        final_ids: List[str] = []\n        for control_id in needed_ids:\n            if control_id not in loaded_ids:\n                control = self._catalog_interface.get_control(control_id)\n                if control is None:\n                    msg = (\n                        f'Profile titled \"{self._profile.metadata.title}\" references control {control_id} '\n                        f'but it is not in catalog titled \"{self._catalog.metadata.title}\"'\n                    )\n                    raise TrestleError(msg)\n                control = self._prune_control(needed_ids, control, loaded_ids)\n                self._catalog_interface.replace_control(control)\n                loaded_ids.append(control_id)\n                final_ids.append(control_id)\n        return final_ids\n\n    def _re_insert_child_controls(self, control: cat.Control) -> cat.Control:\n\"\"\"Re insert this control and its children recursively.\"\"\"\n        new_controls = []\n        for sub_control in as_list(control.controls):\n            new_control = self._re_insert_child_controls(sub_control)\n            new_controls.append(new_control)\n        control.controls = none_if_empty(new_controls)\n        return control\n\n    def _re_insert_children(self) -> None:\n\"\"\"Go through all controls in control dict and load child controls from control dict.\"\"\"\n        for control in self._catalog_interface.get_all_controls_from_dict():\n            _ = self._re_insert_child_controls(control)\n\n    def _prune_catalog(self) -> cat.Catalog:\n\"\"\"Prune the controls in the current catalog.\"\"\"\n        if self._import is None:\n            return self._catalog\n\n        needed_ids = self._find_needed_control_ids()\n\n        # if a control includes controls - only include those that we know are needed\n        final_control_ids = self._prune_controls(needed_ids)\n\n        self._re_insert_children()\n\n        cat_controls = []\n\n        # build the needed groups of controls\n        group_dict: Dict[str, cat.Group] = {}\n        for control_id in final_control_ids:\n            control = self._catalog_interface.get_control(control_id)\n            group_id, group_title, group_class = self._catalog_interface.get_group_info_by_control(control_id)\n            if not group_id:\n                cat_controls.append(control)\n                continue\n            group = group_dict.get(group_id)\n            if group is None:\n                group = cat.Group(id=group_id, title=group_title, class_=group_class, controls=[control])\n                group_dict[group_id] = group\n            else:\n                group_dict[group_id].controls.append(control)\n\n        new_groups: Optional[List[cat.Group]] = list(group_dict.values())\n\n        # should avoid empty lists so set to None if empty\n        new_groups = none_if_empty(new_groups)\n        cat_controls = none_if_empty(cat_controls)\n        new_params = self._catalog.params\n\n        new_cat = cat.Catalog(\n            uuid=str(uuid4()),\n            metadata=self._catalog.metadata,\n            back_matter=common.BackMatter(),\n            controls=cat_controls,\n            groups=new_groups,\n            params=new_params\n        )\n\n        # find all referenced uuids - they should be 1:1 with those in backmatter\n        needed_uuid_refs = ModelUtils.find_uuid_refs(new_cat)\n\n        # prune the list of resources to only those that are needed\n        new_resources: Optional[List[common.Resource]] = []\n        if self._catalog.back_matter and self._catalog.back_matter.resources:\n            new_resources = [res for res in self._catalog.back_matter.resources if res.uuid in needed_uuid_refs]\n        new_resources = none_if_empty(new_resources)\n        new_cat.back_matter.resources = new_resources\n\n        return new_cat\n\n    def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n        Prune the catalog based on the include rule in the import_.\n\n        This only processes the one catalog yielded by the one import in this pipeline.\n        It must yield in order to have the merge filter loop over available imported catalogs.\n        \"\"\"\n        self._set_catalog(next(catalog_iter))\n        logger.debug(f'prune yielding catalog {self._catalog.metadata.title} with import {self._import.href}')\n        yield self._prune_catalog()\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune.__init__","title":"__init__(self, import_, profile) special","text":"

                                                                            Inject the import.

                                                                            This needs to be created prior to knowing the catalog. The profile itself is only needed for debug messages. The import is one possibly several imports in that profile.

                                                                            Source code in trestle/core/resolver/prune.py
                                                                            def __init__(self, import_: prof.Import, profile: prof.Profile) -> None:\n\"\"\"\n    Inject the import.\n\n    This needs to be created prior to knowing the catalog.\n    The profile itself is only needed for debug messages.\n    The import is one possibly several imports in that profile.\n    \"\"\"\n    self._import = import_\n    self._profile = profile\n    self._catalog_interface: Optional[CatalogInterface] = None\n    self._catalog: Optional[cat.Catalog] = None\n
                                                                            "},{"location":"api_reference/trestle.core.resolver.prune/#trestle.core.resolver.prune.Prune.process","title":"process(self, catalog_iter)","text":"

                                                                            Prune the catalog based on the include rule in the import_.

                                                                            This only processes the one catalog yielded by the one import in this pipeline. It must yield in order to have the merge filter loop over available imported catalogs.

                                                                            Source code in trestle/core/resolver/prune.py
                                                                            def process(self, catalog_iter: Iterator[cat.Catalog]) -> Iterator[cat.Catalog]:  # type: ignore\n\"\"\"\n    Prune the catalog based on the include rule in the import_.\n\n    This only processes the one catalog yielded by the one import in this pipeline.\n    It must yield in order to have the merge filter loop over available imported catalogs.\n    \"\"\"\n    self._set_catalog(next(catalog_iter))\n    logger.debug(f'prune yielding catalog {self._catalog.metadata.title} with import {self._import.href}')\n    yield self._prune_catalog()\n
                                                                            "},{"location":"api_reference/trestle.core.rule_parameters_validator/","title":"rule_parameters_validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator","title":"trestle.core.rule_parameters_validator","text":"

                                                                            Validate by confirming rule parameter values are consistent.

                                                                            "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator","title":" RuleParametersValidator (Validator) ","text":"

                                                                            Validator to confirm all rule parameter values are consistent.

                                                                            Source code in trestle/core/rule_parameters_validator.py
                                                                            class RuleParametersValidator(Validator):\n\"\"\"Validator to confirm all rule parameter values are consistent.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize rule param values dictionary.\"\"\"\n        self._rule_param_values_dict: Dict[str, Any] = {}\n\n    def _add_imp_req_rule_params_to_dict(\n        self,\n        imp_requirement: ImplementedRequirement,\n        cat_int: CatalogInterface,\n    ) -> None:\n\"\"\"\n        Iterate all by components in an object and add the rule shared parameter values to list.\n\n        args:\n            imp_requirement: Current implemented requirement.\n            cat_int: Instance of catalog interface with controls catalog loaded.\n        \"\"\"\n        for by_component in as_list(imp_requirement.by_components):\n            # adds rule param values present in set parameters for current imp req\n            self._add_rule_params(imp_requirement, imp_requirement.control_id, cat_int, by_component.component_uuid)\n            # adds rule param values present in set parameters for current by_component in by_components list\n            # in the current implemented requirement\n            self._add_rule_params(by_component, imp_requirement.control_id, cat_int, by_component.component_uuid)\n            for statement in as_list(imp_requirement.statements):\n                # iterates by each by component inclded at each statemtent set for current imp req\n                for by_comp in as_list(statement.by_components):\n                    # adds rule param values present in set parameters for current by_component in by_components list\n                    # of current statement in current implemented requirement\n                    self._add_rule_params(by_comp, imp_requirement.control_id, cat_int, by_comp.component_uuid)\n\n    def _add_rule_params(\n        self, item: TypeWithSetParams, control_id: str, cat_int: CatalogInterface, comp_uuid: str = ''\n    ) -> None:\n\"\"\"\n        Add a rule shared parameter to the rule shared parameters list.\n\n        args:\n            item: Generic item to iterate over parameters.\n            control_id: Current control id.\n            cat_int: Instance of catalog interface with controls catalog loaded.\n            comp_uuid: Component uuid to save.\n        \"\"\"\n        for set_param in as_list(item.set_parameters):\n            # validates if current param_id is or not associated with a control so we can assume it\u00b4s a rule param\n            control = cat_int.get_control_by_param_id(set_param.param_id)\n            if not control:\n                deep_set(self._rule_param_values_dict, [set_param.param_id, comp_uuid, control_id], set_param.values)\n\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Test if the model is valid.\n\n        args:\n            model: A top level OSCAL model.\n            quiet: Don't report msgs unless invalid.\n            trestle_root: Trestle root path.\n\n        returns:\n            True (valid) if the model's rule parameter values are the same across controls.\n        \"\"\"\n        # verify if model type is either an SSP of a Component Definition\n        if not isinstance(model, SystemSecurityPlan):\n            return True\n\n        if not model.import_profile.href:\n            logger.info(f'INVALID: Model {model.metadata.title} has no referenced profile')\n            return False\n        profile_catalog = ProfileResolver().get_resolved_profile_catalog(trestle_root, model.import_profile.href)\n        catalog_interface = CatalogInterface(profile_catalog)\n        # iterate by each implemented requirement defined\n        for imp_req in model.control_implementation.implemented_requirements:\n            # adds rule param values to dict by implemented requirement basis\n            self._add_imp_req_rule_params_to_dict(imp_req, catalog_interface)\n        if self._rule_param_values_dict:\n            # compare all values in shared paramerets by component basis\n            for shared_param, values_dict in self._rule_param_values_dict.items():\n                for comp_name, value_dict in values_dict.items():\n                    expected_value = next(iter(value_dict.values()))\n                    if not all(value == expected_value for value in value_dict.values()):\n                        logger.error(\n                            f'Rule parameter values for param: {shared_param} in '\n                            f' {comp_name} are not consistent with '\n                            'other values provided across controls. Invalid model'\n                        )\n                        return False\n        return True\n
                                                                            "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator.__init__","title":"__init__(self) special","text":"

                                                                            Initialize rule param values dictionary.

                                                                            Source code in trestle/core/rule_parameters_validator.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize rule param values dictionary.\"\"\"\n    self._rule_param_values_dict: Dict[str, Any] = {}\n
                                                                            "},{"location":"api_reference/trestle.core.rule_parameters_validator/#trestle.core.rule_parameters_validator.RuleParametersValidator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                                                            Test if the model is valid.

                                                                            Parameters:

                                                                            Name Type Description Default model ~TopLevelOscalModel

                                                                            A top level OSCAL model.

                                                                            required quiet bool

                                                                            Don't report msgs unless invalid.

                                                                            required trestle_root Optional[pathlib.Path]

                                                                            Trestle root path.

                                                                            None

                                                                            Returns:

                                                                            Type Description bool

                                                                            True (valid) if the model's rule parameter values are the same across controls.

                                                                            Source code in trestle/core/rule_parameters_validator.py
                                                                            def model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Test if the model is valid.\n\n    args:\n        model: A top level OSCAL model.\n        quiet: Don't report msgs unless invalid.\n        trestle_root: Trestle root path.\n\n    returns:\n        True (valid) if the model's rule parameter values are the same across controls.\n    \"\"\"\n    # verify if model type is either an SSP of a Component Definition\n    if not isinstance(model, SystemSecurityPlan):\n        return True\n\n    if not model.import_profile.href:\n        logger.info(f'INVALID: Model {model.metadata.title} has no referenced profile')\n        return False\n    profile_catalog = ProfileResolver().get_resolved_profile_catalog(trestle_root, model.import_profile.href)\n    catalog_interface = CatalogInterface(profile_catalog)\n    # iterate by each implemented requirement defined\n    for imp_req in model.control_implementation.implemented_requirements:\n        # adds rule param values to dict by implemented requirement basis\n        self._add_imp_req_rule_params_to_dict(imp_req, catalog_interface)\n    if self._rule_param_values_dict:\n        # compare all values in shared paramerets by component basis\n        for shared_param, values_dict in self._rule_param_values_dict.items():\n            for comp_name, value_dict in values_dict.items():\n                expected_value = next(iter(value_dict.values()))\n                if not all(value == expected_value for value in value_dict.values()):\n                    logger.error(\n                        f'Rule parameter values for param: {shared_param} in '\n                        f' {comp_name} are not consistent with '\n                        'other values provided across controls. Invalid model'\n                    )\n                    return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/","title":"ssp_io","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io","title":"trestle.core.ssp_io","text":"

                                                                            Handle direct IO for writing SSP responses as markdown.

                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter","title":" SSPMarkdownWriter ","text":"

                                                                            Class to write control responses as markdown.

                                                                            Functions in this class are mainly used by jinja and not by the trestle code itself.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            class SSPMarkdownWriter():\n\"\"\"\n    Class to write control responses as markdown.\n\n    Functions in this class are mainly used by jinja and not by the trestle code itself.\n    \"\"\"\n\n    def __init__(self, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n        self._trestle_root = trestle_root\n        self._ssp: ssp.SystemSecurityPlan = None\n        self._resolved_catalog: Catalog = None\n        self._catalog_interface: CatalogInterface = None\n\n    def set_ssp(self, ssp: ssp.SystemSecurityPlan) -> None:\n\"\"\"Set ssp.\"\"\"\n        self._ssp = ssp\n\n    def set_catalog(self, resolved_catalog: Catalog) -> None:\n\"\"\"Set catalog.\"\"\"\n        self._resolved_catalog = resolved_catalog\n        self._catalog_interface = catalog_interface.CatalogInterface(self._resolved_catalog)\n\n    def get_control_statement(self, control_id: str, level: int) -> str:\n\"\"\"\n        Get the control statement for an ssp - to be printed in markdown as a structured list.\n\n        Args:\n            control_id: The control_id to use.\n\n        Returns:\n            A markdown blob as a string.\n        \"\"\"\n        if not self._resolved_catalog:\n            raise TrestleError('Cannot get control statement, set resolved catalog first.')\n\n        writer = DocsControlWriter()\n        control = self._catalog_interface.get_control(control_id)\n        if not control:\n            return ''\n\n        control_lines = writer.get_control_statement_ssp(control)\n\n        return self._build_tree_and_adjust(control_lines, level)\n\n    def get_control_part(self, control_id: str, part_name: str, level: int) -> str:\n\"\"\"Get control part with given name.\"\"\"\n        control_part = self._catalog_interface.get_control_part_prose(control_id, part_name)\n\n        md_list = self._write_str_with_header(\n            f'Control Part: {part_name} for control: {control_id}', control_part, level\n        )\n        return self._build_tree_and_adjust(md_list.split('\\n'), level)\n\n    def get_fedramp_control_tables(self, control_id: str, level: int, label_column: bool = False) -> str:\n\"\"\"Get the fedramp metadata as markdown tables, with optional third label column for params.\n\n        The fedramp metadata has the following elements:\n        - Responsible roles field\n        - Parameter values table\n        - Implementation status field\n        - Control origination field\n\n        Returns:\n            tables as one coherent markdown blob.\n        \"\"\"\n        resp_roles_table = self.get_responsible_roles_table(control_id, level)\n        params_values = self._parameter_table(control_id, level, label_column)\n        impl_status = self.get_fedramp_implementation_status(control_id, level)\n        control_orig = self.get_fedramp_control_origination(control_id, level)\n\n        final_output = ''\n        if resp_roles_table:\n            final_output += resp_roles_table\n        if params_values:\n            final_output += '\\n' + params_values\n        if impl_status:\n            final_output += '\\n' + impl_status\n        if control_orig:\n            final_output += '\\n' + control_orig\n        return final_output\n\n    def get_responsible_roles_table(self, control_id: str, level: int) -> str:\n\"\"\"\n        For each role id - if the role exists in metadata use the title as what gets printed in the roles table.\n\n        If not (for now) warn and use the role-id as the printed text.\n        \"\"\"\n        if self._ssp is None:\n            raise TrestleError('Cannot get responsible roles, SSP is not set.')\n\n        for impl_requirement in self._ssp.control_implementation.implemented_requirements:\n            if impl_requirement.control_id == control_id:\n                if impl_requirement.responsible_roles:\n                    resp_roles = as_list(impl_requirement.responsible_roles)\n                    role_ids = [role.role_id.replace('_', ' ') for role in resp_roles]\n\n                    # now check if this role exists in the metadata\n                    role_titles = dict(zip(role_ids, role_ids))\n                    roles = as_list(self._ssp.metadata.roles)\n                    for role in roles:\n                        if role.id in role_ids:\n                            role_titles[role.id] = role.title\n\n                    # dictionary to md table\n                    md_list = self._write_table_with_header(\n                        'Responsible Roles.', [[key, role_titles[key]] for key in role_titles.keys()],\n                        ['Role ID', 'Title'],\n                        level\n                    )\n                    return md_list\n                else:\n                    logger.warning(\n                        f'No responsible roles were found for the control with id: {control_id} in given SSP.'\n                    )\n                    return ''\n\n        return ''\n\n    def _parameter_table(self, control_id: str, level: int, label_column: bool = False) -> str:\n\"\"\"Print Param_id | ValueOrLabelOrChoices | Optional Label Column.\"\"\"\n        if not self._ssp:\n            raise TrestleError('Cannot get parameter table, set SSP first.')\n\n        writer = DocsControlWriter()\n        control = self._catalog_interface.get_control(control_id)\n        if not control:\n            return ''\n        params_lines = writer.get_param_table(control, label_column)\n        # need to make sure no params still have moustaches.  convert to brackets to avoid jinja complaints\n        clean_lines = []\n        for line in params_lines:\n            clean_lines.append(line.replace('{{', '[[').replace('}}', ']]'))\n\n        tree = DocsMarkdownNode.build_tree_from_markdown(clean_lines)\n        tree.change_header_level_by(level)\n        return tree.content.raw_text\n\n    def get_fedramp_implementation_status(self, control_id: str, level: int) -> str:\n\"\"\"\n        Print implementation status as a list of items, only showing those that are applicable for the control.\n\n        This is unlike the word document FedRAMP which uses checkboxes on standard set of options.\n        Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n        \"\"\"\n        if not self._ssp:\n            raise TrestleError('Cannot get Fedramp implementation status, set SSP first.')\n\n        implementation_statuses: List[str] = []\n        control_impl_req = self._control_implemented_req(control_id)\n        if control_impl_req and control_impl_req.props:\n            for prop in control_impl_req.props:\n                if prop.name == IMPLEMENTATION_STATUS:\n                    implementation_statuses.append(prop.value)\n\n        md_list = self._write_list_with_header('FedRamp Implementation Status.', implementation_statuses, level)\n        return md_list\n\n    def get_fedramp_control_origination(self, control_id: str, level: int) -> str:\n\"\"\"\n        Print control origination, as a list of items, only showing those that are applicable for the control.\n\n        Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n        \"\"\"\n        if not self._ssp:\n            raise TrestleError('Cannot get FedRamp control origination, set SSP first.')\n\n        control_origination = []\n        control_impl_req = self._control_implemented_req(control_id)\n\n        if control_impl_req and control_impl_req.props:\n            for prop in control_impl_req.props:\n                if prop.name == CONTROL_ORIGINATION:\n                    control_origination.append(prop.value)\n\n        md_list = self._write_list_with_header('FedRamp Control Origination.', control_origination, level)\n        return md_list\n\n    @staticmethod\n    def _write_component_prompt(\n        md_writer: MDWriter,\n        comp_name: str,\n        prose: str,\n        rules: List[str],\n        status: str,\n        show_rules: bool,\n        show_status: bool\n    ) -> None:\n        header = f'Component: {comp_name}'\n        md_writer.new_header(1, header)\n        md_writer.set_indent_level(-1)\n        md_writer.new_line(prose)\n        md_writer.set_indent_level(-1)\n        if rules and show_rules:\n            md_writer.new_header(2, title='Rules:')\n            md_writer.set_indent_level(-1)\n            md_writer.new_list(rules)\n            md_writer.set_indent_level(-1)\n        if status and show_status:\n            md_writer.new_header(2, title=f'Implementation Status: {status}')\n\n    def get_control_response(\n        self,\n        control_id: str,\n        level: int,\n        write_empty_responses: bool = False,\n        show_comp: bool = True,\n        show_rules: bool = False,\n        show_status: bool = True\n    ) -> str:\n\"\"\"\n        Get the full control implemented requirements, broken down based on the available control responses.\n\n        Args:\n            control_id: id of the control\n            level: level of indentation\n            write_empty_responses: write response even if empty\n            show_comp: show the component name in the response\n\n        Notes:\n            This is intended to be invoked from a jinja template that has already written out the prompt for\n            control response\n        \"\"\"\n        if not self._resolved_catalog:\n            raise TrestleError('Cannot get control response, set resolved catalog first.')\n\n        control = self._catalog_interface.get_control(control_id)\n        imp_req = self._control_implemented_req(control_id)\n        if not imp_req:\n            logger.info(f'No implemented requirements found for the control {control_id}')\n            return ''\n\n        md_writer = MDWriter(None)\n\n        system_prose = ''\n        system_rules = []\n        system_status = STATUS_OPERATIONAL\n        imp_req_responses = self._get_responses_by_components(imp_req, write_empty_responses)\n        if SSP_MAIN_COMP_NAME in imp_req_responses:\n            system_prose, system_rules, system_status = imp_req_responses[SSP_MAIN_COMP_NAME]\n\n        SSPMarkdownWriter._write_component_prompt(\n            md_writer, SSP_MAIN_COMP_NAME, system_prose, system_rules, system_status, show_rules, show_status\n        )\n\n        # if a control has no statement sub-parts then get the response bycomps from the imp_req itself\n        # otherwise get them from the statements in the imp_req\n        # an imp_req and a statement are both things that can have bycomps\n        has_bycomps = imp_req.statements if imp_req.statements else [imp_req]\n        for has_bycomp in has_bycomps:\n            statement_id = getattr(has_bycomp, 'statement_id', f'{control_id}_smt')\n            label = statement_id\n            part_name = None\n\n            # look up label for this statement\n            if control.parts:\n                found_label, part = self._catalog_interface.get_statement_label_if_exists(control_id, statement_id)\n                if found_label:\n                    label = found_label\n                    part_name = part.name\n\n            response_per_component = self._get_responses_by_components(has_bycomp, write_empty_responses)\n\n            if response_per_component or write_empty_responses:\n                if part_name and part_name == ITEM:\n                    # print part header only if subitem\n                    header = f'Implementation for part {label}'\n                    md_writer.new_header(1, title=header)\n                for comp_name, comp_response in response_per_component.items():\n                    if comp_name == SSP_MAIN_COMP_NAME:\n                        continue\n                    prose, rules, status = comp_response\n                    if show_comp:\n                        SSPMarkdownWriter._write_component_prompt(\n                            md_writer, comp_name, prose, rules, status, show_rules, show_status\n                        )\n\n        lines = md_writer.get_lines()\n\n        tree = DocsMarkdownNode.build_tree_from_markdown(lines)\n        tree.change_header_level_by(level)\n\n        return tree.content.raw_text\n\n    def _get_responses_by_components(self, has_bycomps: TypeWithByComps,\n                                     write_empty_responses: bool) -> Dict[str, Tuple[str, List[str], str]]:\n\"\"\"Get response per component, substitute component id with title if possible.\"\"\"\n        response_per_component: Dict[str, Tuple[str, str]] = {}\n        for by_comp in as_list(has_bycomps.by_components):  # type: ignore\n            # look up component title\n            subheader = by_comp.component_uuid\n            prose = ''\n            status = ''\n            rules = []\n            if self._ssp.system_implementation.components:\n                for comp in self._ssp.system_implementation.components:\n                    if comp.uuid == by_comp.component_uuid:\n                        title = comp.title\n                        if title:\n                            subheader = title\n            if by_comp.description:\n                prose = by_comp.description\n            if by_comp.implementation_status:\n                status = by_comp.implementation_status.state\n            rules, _ = ControlInterface.get_rule_list_for_item(by_comp)\n\n            if prose or (not prose and write_empty_responses):\n                if subheader:\n                    response_per_component[subheader] = (prose, rules, status)\n\n        return response_per_component\n\n    def _control_implemented_req(self, control_id: str) -> Optional[ssp.ImplementedRequirement]:\n\"\"\"Retrieve control implemented requirement by control-id.\"\"\"\n        requirements = self._ssp.control_implementation.implemented_requirements\n        for requirement in requirements:\n            if requirement.control_id == control_id:\n                return requirement\n        logger.debug(f'No implemented requirement found for control {control_id}')\n        return None\n\n    def _write_list_with_header(self, header: str, lines: List[str], level: int) -> str:\n        if lines:\n            md_writer = MDWriter(None)\n            md_writer.new_paragraph()\n            md_writer.new_header(level=1, title=header)\n            md_writer.set_indent_level(-1)\n            md_writer.new_list(lines)\n            md_writer.set_indent_level(-1)\n\n            return self._build_tree_and_adjust(md_writer.get_lines(), level)\n\n        return ''\n\n    def _write_table_with_header(\n        self, header: str, values: List[List[str]], table_header: List[str], level: int\n    ) -> str:\n        if values and values[0]:\n            md_writer = MDWriter(None)\n            md_writer.new_paragraph()\n            md_writer.new_header(level=1, title=header)\n            md_writer.set_indent_level(-1)\n            md_writer.new_table(values, table_header)\n            md_writer.set_indent_level(-1)\n\n            return self._build_tree_and_adjust(md_writer.get_lines(), level)\n        return ''\n\n    def _write_str_with_header(self, header: str, text: str, level: int) -> str:\n        if text:\n            md_writer = MDWriter(None)\n            md_writer.new_paragraph()\n            md_writer.new_header(level=1, title=header)\n            md_writer.set_indent_level(-1)\n            md_writer.new_line(text)\n            md_writer.set_indent_level(-1)\n\n            return self._build_tree_and_adjust(md_writer.get_lines(), level)\n        return ''\n\n    def _build_tree_and_adjust(self, lines: List[str], level: int) -> str:\n        tree = DocsMarkdownNode.build_tree_from_markdown(lines)\n        tree.change_header_level_by(level)\n\n        return tree.content.raw_text\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.__init__","title":"__init__(self, trestle_root) special","text":"

                                                                            Initialize the class.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def __init__(self, trestle_root: pathlib.Path) -> None:\n\"\"\"Initialize the class.\"\"\"\n    self._trestle_root = trestle_root\n    self._ssp: ssp.SystemSecurityPlan = None\n    self._resolved_catalog: Catalog = None\n    self._catalog_interface: CatalogInterface = None\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_control_part","title":"get_control_part(self, control_id, part_name, level)","text":"

                                                                            Get control part with given name.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def get_control_part(self, control_id: str, part_name: str, level: int) -> str:\n\"\"\"Get control part with given name.\"\"\"\n    control_part = self._catalog_interface.get_control_part_prose(control_id, part_name)\n\n    md_list = self._write_str_with_header(\n        f'Control Part: {part_name} for control: {control_id}', control_part, level\n    )\n    return self._build_tree_and_adjust(md_list.split('\\n'), level)\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_control_response","title":"get_control_response(self, control_id, level, write_empty_responses=False, show_comp=True, show_rules=False, show_status=True)","text":"

                                                                            Get the full control implemented requirements, broken down based on the available control responses.

                                                                            Parameters:

                                                                            Name Type Description Default control_id str

                                                                            id of the control

                                                                            required level int

                                                                            level of indentation

                                                                            required write_empty_responses bool

                                                                            write response even if empty

                                                                            False show_comp bool

                                                                            show the component name in the response

                                                                            True

                                                                            Notes

                                                                            This is intended to be invoked from a jinja template that has already written out the prompt for control response

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def get_control_response(\n    self,\n    control_id: str,\n    level: int,\n    write_empty_responses: bool = False,\n    show_comp: bool = True,\n    show_rules: bool = False,\n    show_status: bool = True\n) -> str:\n\"\"\"\n    Get the full control implemented requirements, broken down based on the available control responses.\n\n    Args:\n        control_id: id of the control\n        level: level of indentation\n        write_empty_responses: write response even if empty\n        show_comp: show the component name in the response\n\n    Notes:\n        This is intended to be invoked from a jinja template that has already written out the prompt for\n        control response\n    \"\"\"\n    if not self._resolved_catalog:\n        raise TrestleError('Cannot get control response, set resolved catalog first.')\n\n    control = self._catalog_interface.get_control(control_id)\n    imp_req = self._control_implemented_req(control_id)\n    if not imp_req:\n        logger.info(f'No implemented requirements found for the control {control_id}')\n        return ''\n\n    md_writer = MDWriter(None)\n\n    system_prose = ''\n    system_rules = []\n    system_status = STATUS_OPERATIONAL\n    imp_req_responses = self._get_responses_by_components(imp_req, write_empty_responses)\n    if SSP_MAIN_COMP_NAME in imp_req_responses:\n        system_prose, system_rules, system_status = imp_req_responses[SSP_MAIN_COMP_NAME]\n\n    SSPMarkdownWriter._write_component_prompt(\n        md_writer, SSP_MAIN_COMP_NAME, system_prose, system_rules, system_status, show_rules, show_status\n    )\n\n    # if a control has no statement sub-parts then get the response bycomps from the imp_req itself\n    # otherwise get them from the statements in the imp_req\n    # an imp_req and a statement are both things that can have bycomps\n    has_bycomps = imp_req.statements if imp_req.statements else [imp_req]\n    for has_bycomp in has_bycomps:\n        statement_id = getattr(has_bycomp, 'statement_id', f'{control_id}_smt')\n        label = statement_id\n        part_name = None\n\n        # look up label for this statement\n        if control.parts:\n            found_label, part = self._catalog_interface.get_statement_label_if_exists(control_id, statement_id)\n            if found_label:\n                label = found_label\n                part_name = part.name\n\n        response_per_component = self._get_responses_by_components(has_bycomp, write_empty_responses)\n\n        if response_per_component or write_empty_responses:\n            if part_name and part_name == ITEM:\n                # print part header only if subitem\n                header = f'Implementation for part {label}'\n                md_writer.new_header(1, title=header)\n            for comp_name, comp_response in response_per_component.items():\n                if comp_name == SSP_MAIN_COMP_NAME:\n                    continue\n                prose, rules, status = comp_response\n                if show_comp:\n                    SSPMarkdownWriter._write_component_prompt(\n                        md_writer, comp_name, prose, rules, status, show_rules, show_status\n                    )\n\n    lines = md_writer.get_lines()\n\n    tree = DocsMarkdownNode.build_tree_from_markdown(lines)\n    tree.change_header_level_by(level)\n\n    return tree.content.raw_text\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_control_statement","title":"get_control_statement(self, control_id, level)","text":"

                                                                            Get the control statement for an ssp - to be printed in markdown as a structured list.

                                                                            Parameters:

                                                                            Name Type Description Default control_id str

                                                                            The control_id to use.

                                                                            required

                                                                            Returns:

                                                                            Type Description str

                                                                            A markdown blob as a string.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def get_control_statement(self, control_id: str, level: int) -> str:\n\"\"\"\n    Get the control statement for an ssp - to be printed in markdown as a structured list.\n\n    Args:\n        control_id: The control_id to use.\n\n    Returns:\n        A markdown blob as a string.\n    \"\"\"\n    if not self._resolved_catalog:\n        raise TrestleError('Cannot get control statement, set resolved catalog first.')\n\n    writer = DocsControlWriter()\n    control = self._catalog_interface.get_control(control_id)\n    if not control:\n        return ''\n\n    control_lines = writer.get_control_statement_ssp(control)\n\n    return self._build_tree_and_adjust(control_lines, level)\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_fedramp_control_origination","title":"get_fedramp_control_origination(self, control_id, level)","text":"

                                                                            Print control origination, as a list of items, only showing those that are applicable for the control.

                                                                            Using a LUT to map between structured data fields, defined by FedRAMP and historical text.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def get_fedramp_control_origination(self, control_id: str, level: int) -> str:\n\"\"\"\n    Print control origination, as a list of items, only showing those that are applicable for the control.\n\n    Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n    \"\"\"\n    if not self._ssp:\n        raise TrestleError('Cannot get FedRamp control origination, set SSP first.')\n\n    control_origination = []\n    control_impl_req = self._control_implemented_req(control_id)\n\n    if control_impl_req and control_impl_req.props:\n        for prop in control_impl_req.props:\n            if prop.name == CONTROL_ORIGINATION:\n                control_origination.append(prop.value)\n\n    md_list = self._write_list_with_header('FedRamp Control Origination.', control_origination, level)\n    return md_list\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_fedramp_control_tables","title":"get_fedramp_control_tables(self, control_id, level, label_column=False)","text":"

                                                                            Get the fedramp metadata as markdown tables, with optional third label column for params.

                                                                            The fedramp metadata has the following elements: - Responsible roles field - Parameter values table - Implementation status field - Control origination field

                                                                            Returns:

                                                                            Type Description str

                                                                            tables as one coherent markdown blob.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def get_fedramp_control_tables(self, control_id: str, level: int, label_column: bool = False) -> str:\n\"\"\"Get the fedramp metadata as markdown tables, with optional third label column for params.\n\n    The fedramp metadata has the following elements:\n    - Responsible roles field\n    - Parameter values table\n    - Implementation status field\n    - Control origination field\n\n    Returns:\n        tables as one coherent markdown blob.\n    \"\"\"\n    resp_roles_table = self.get_responsible_roles_table(control_id, level)\n    params_values = self._parameter_table(control_id, level, label_column)\n    impl_status = self.get_fedramp_implementation_status(control_id, level)\n    control_orig = self.get_fedramp_control_origination(control_id, level)\n\n    final_output = ''\n    if resp_roles_table:\n        final_output += resp_roles_table\n    if params_values:\n        final_output += '\\n' + params_values\n    if impl_status:\n        final_output += '\\n' + impl_status\n    if control_orig:\n        final_output += '\\n' + control_orig\n    return final_output\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_fedramp_implementation_status","title":"get_fedramp_implementation_status(self, control_id, level)","text":"

                                                                            Print implementation status as a list of items, only showing those that are applicable for the control.

                                                                            This is unlike the word document FedRAMP which uses checkboxes on standard set of options. Using a LUT to map between structured data fields, defined by FedRAMP and historical text.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def get_fedramp_implementation_status(self, control_id: str, level: int) -> str:\n\"\"\"\n    Print implementation status as a list of items, only showing those that are applicable for the control.\n\n    This is unlike the word document FedRAMP which uses checkboxes on standard set of options.\n    Using a LUT to map between structured data fields, defined by FedRAMP and historical text.\n    \"\"\"\n    if not self._ssp:\n        raise TrestleError('Cannot get Fedramp implementation status, set SSP first.')\n\n    implementation_statuses: List[str] = []\n    control_impl_req = self._control_implemented_req(control_id)\n    if control_impl_req and control_impl_req.props:\n        for prop in control_impl_req.props:\n            if prop.name == IMPLEMENTATION_STATUS:\n                implementation_statuses.append(prop.value)\n\n    md_list = self._write_list_with_header('FedRamp Implementation Status.', implementation_statuses, level)\n    return md_list\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.get_responsible_roles_table","title":"get_responsible_roles_table(self, control_id, level)","text":"

                                                                            For each role id - if the role exists in metadata use the title as what gets printed in the roles table.

                                                                            If not (for now) warn and use the role-id as the printed text.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def get_responsible_roles_table(self, control_id: str, level: int) -> str:\n\"\"\"\n    For each role id - if the role exists in metadata use the title as what gets printed in the roles table.\n\n    If not (for now) warn and use the role-id as the printed text.\n    \"\"\"\n    if self._ssp is None:\n        raise TrestleError('Cannot get responsible roles, SSP is not set.')\n\n    for impl_requirement in self._ssp.control_implementation.implemented_requirements:\n        if impl_requirement.control_id == control_id:\n            if impl_requirement.responsible_roles:\n                resp_roles = as_list(impl_requirement.responsible_roles)\n                role_ids = [role.role_id.replace('_', ' ') for role in resp_roles]\n\n                # now check if this role exists in the metadata\n                role_titles = dict(zip(role_ids, role_ids))\n                roles = as_list(self._ssp.metadata.roles)\n                for role in roles:\n                    if role.id in role_ids:\n                        role_titles[role.id] = role.title\n\n                # dictionary to md table\n                md_list = self._write_table_with_header(\n                    'Responsible Roles.', [[key, role_titles[key]] for key in role_titles.keys()],\n                    ['Role ID', 'Title'],\n                    level\n                )\n                return md_list\n            else:\n                logger.warning(\n                    f'No responsible roles were found for the control with id: {control_id} in given SSP.'\n                )\n                return ''\n\n    return ''\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.set_catalog","title":"set_catalog(self, resolved_catalog)","text":"

                                                                            Set catalog.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def set_catalog(self, resolved_catalog: Catalog) -> None:\n\"\"\"Set catalog.\"\"\"\n    self._resolved_catalog = resolved_catalog\n    self._catalog_interface = catalog_interface.CatalogInterface(self._resolved_catalog)\n
                                                                            "},{"location":"api_reference/trestle.core.ssp_io/#trestle.core.ssp_io.SSPMarkdownWriter.set_ssp","title":"set_ssp(self, ssp)","text":"

                                                                            Set ssp.

                                                                            Source code in trestle/core/ssp_io.py
                                                                            def set_ssp(self, ssp: ssp.SystemSecurityPlan) -> None:\n\"\"\"Set ssp.\"\"\"\n    self._ssp = ssp\n
                                                                            "},{"location":"api_reference/trestle.core.trestle_base_model/","title":"trestle_base_model","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model","title":"trestle.core.trestle_base_model","text":"

                                                                            Trestle Base Model.

                                                                            "},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.Model","title":"Model","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel","title":" TrestleBaseModel (BaseModel) pydantic-model","text":"

                                                                            Trestle Base Model. Serves as wrapper around BaseModel for overriding methods.

                                                                            Source code in trestle/core/trestle_base_model.py
                                                                            class TrestleBaseModel(BaseModel):\n\"\"\"Trestle Base Model. Serves as wrapper around BaseModel for overriding methods.\"\"\"\n\n    @classmethod\n    def parse_obj(cls: Type['Model'], obj: Any) -> 'Model':\n\"\"\"Parse object to the given class.\"\"\"\n        try:\n            return super().parse_obj(obj)\n        except ValidationError as e:\n            # check if failed due to the wrong OSCAL version:\n            oscal_version_error = False\n            for err in e.errors():\n                for field in err['loc']:\n                    if field == 'oscal-version':\n                        message = err['msg']\n                        oscal_version_error = True\n                        break\n            if oscal_version_error:\n                raise TrestleError(f'{message}')\n            else:\n                raise\n
                                                                            "},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.trestle_base_model/#trestle.core.trestle_base_model.TrestleBaseModel.parse_obj","title":"parse_obj(obj) classmethod","text":"

                                                                            Parse object to the given class.

                                                                            Source code in trestle/core/trestle_base_model.py
                                                                            @classmethod\ndef parse_obj(cls: Type['Model'], obj: Any) -> 'Model':\n\"\"\"Parse object to the given class.\"\"\"\n    try:\n        return super().parse_obj(obj)\n    except ValidationError as e:\n        # check if failed due to the wrong OSCAL version:\n        oscal_version_error = False\n        for err in e.errors():\n            for field in err['loc']:\n                if field == 'oscal-version':\n                    message = err['msg']\n                    oscal_version_error = True\n                    break\n        if oscal_version_error:\n            raise TrestleError(f'{message}')\n        else:\n            raise\n
                                                                            "},{"location":"api_reference/trestle.core.validator/","title":"validator","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator","title":"trestle.core.validator","text":"

                                                                            Base class for all validators.

                                                                            "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.logger","title":"logger","text":""},{"location":"api_reference/trestle.core.validator/#trestle.core.validator-classes","title":"Classes","text":""},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator","title":" Validator (ABC) ","text":"

                                                                            Validator base class.

                                                                            Source code in trestle/core/validator.py
                                                                            class Validator(ABC):\n\"\"\"Validator base class.\"\"\"\n\n    def error_msg(self) -> Optional[str]:\n\"\"\"Error message used to describe this validator.\"\"\"\n        # subclasses can override as needed\n        return self.__doc__\n\n    @abstractmethod\n    def model_is_valid(\n        self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n    ) -> bool:\n\"\"\"\n        Validate the model.\n\n        args:\n            model: An Oscal model that can be passed to the validator.\n            quiet: Don't report msgs unless invalid.\n\n        returns:\n            Whether or not the model passed this validation test.\n        \"\"\"\n\n    def validate(self, args: argparse.Namespace) -> int:\n\"\"\"Perform the validation according to user options.\"\"\"\n        trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n\n        # validate by type - all of type or just specified by name\n        if args.type:\n            models = []\n            if args.name:\n                models = [args.name]\n            else:\n                models = ModelUtils.get_models_of_type(args.type, trestle_root)\n            models_path = trestle_root / ModelUtils.model_type_to_model_dir(args.type)\n            for m in models:\n                model_path = models_path / m\n                try:\n                    _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n                except TrestleError as e:\n                    logger.warning(f'File load error {e}')\n                    return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n                if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                    logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                    return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n                if not args.quiet:\n                    logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n            return CmdReturnCodes.SUCCESS.value\n\n        # validate all\n        if args.all:\n            model_tups = ModelUtils.get_all_models(trestle_root)\n            for mt in model_tups:\n\n                model_dir = trestle_root / ModelUtils.model_type_to_model_dir(mt[0]) / mt[1]\n                extension_type = trestle.common.file_utils.get_contextual_file_type(model_dir)\n                model_path = model_dir / f'{mt[0]}{FileContentType.to_file_extension(extension_type)}'\n                _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n                if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                    logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                    return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n                if not args.quiet:\n                    logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n            return CmdReturnCodes.SUCCESS.value\n\n        # validate file\n        if args.file:\n            file_path = trestle_root / args.file\n            _, _, model = ModelUtils.load_distributed(file_path, trestle_root)\n            if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                logger.info(f'INVALID: Model {file_path} did not pass the {self.error_msg()}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not args.quiet:\n                logger.info(f'VALID: Model {file_path} passed the {self.error_msg()}')\n        return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator-methods","title":"Methods","text":""},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator.error_msg","title":"error_msg(self)","text":"

                                                                            Error message used to describe this validator.

                                                                            Source code in trestle/core/validator.py
                                                                            def error_msg(self) -> Optional[str]:\n\"\"\"Error message used to describe this validator.\"\"\"\n    # subclasses can override as needed\n    return self.__doc__\n
                                                                            "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator.model_is_valid","title":"model_is_valid(self, model, quiet, trestle_root=None)","text":"

                                                                            Validate the model.

                                                                            Parameters:

                                                                            Name Type Description Default model ~TopLevelOscalModel

                                                                            An Oscal model that can be passed to the validator.

                                                                            required quiet bool

                                                                            Don't report msgs unless invalid.

                                                                            required

                                                                            Returns:

                                                                            Type Description bool

                                                                            Whether or not the model passed this validation test.

                                                                            Source code in trestle/core/validator.py
                                                                            @abstractmethod\ndef model_is_valid(\n    self, model: TopLevelOscalModel, quiet: bool, trestle_root: Optional[pathlib.Path] = None\n) -> bool:\n\"\"\"\n    Validate the model.\n\n    args:\n        model: An Oscal model that can be passed to the validator.\n        quiet: Don't report msgs unless invalid.\n\n    returns:\n        Whether or not the model passed this validation test.\n    \"\"\"\n
                                                                            "},{"location":"api_reference/trestle.core.validator/#trestle.core.validator.Validator.validate","title":"validate(self, args)","text":"

                                                                            Perform the validation according to user options.

                                                                            Source code in trestle/core/validator.py
                                                                            def validate(self, args: argparse.Namespace) -> int:\n\"\"\"Perform the validation according to user options.\"\"\"\n    trestle_root = args.trestle_root  # trestle root is set via command line in args. Default is cwd.\n\n    # validate by type - all of type or just specified by name\n    if args.type:\n        models = []\n        if args.name:\n            models = [args.name]\n        else:\n            models = ModelUtils.get_models_of_type(args.type, trestle_root)\n        models_path = trestle_root / ModelUtils.model_type_to_model_dir(args.type)\n        for m in models:\n            model_path = models_path / m\n            try:\n                _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n            except TrestleError as e:\n                logger.warning(f'File load error {e}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not args.quiet:\n                logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n        return CmdReturnCodes.SUCCESS.value\n\n    # validate all\n    if args.all:\n        model_tups = ModelUtils.get_all_models(trestle_root)\n        for mt in model_tups:\n\n            model_dir = trestle_root / ModelUtils.model_type_to_model_dir(mt[0]) / mt[1]\n            extension_type = trestle.common.file_utils.get_contextual_file_type(model_dir)\n            model_path = model_dir / f'{mt[0]}{FileContentType.to_file_extension(extension_type)}'\n            _, _, model = ModelUtils.load_distributed(model_path, trestle_root)\n            if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n                logger.info(f'INVALID: Model {model_path} did not pass the {self.error_msg()}')\n                return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n            if not args.quiet:\n                logger.info(f'VALID: Model {model_path} passed the {self.error_msg()}')\n        return CmdReturnCodes.SUCCESS.value\n\n    # validate file\n    if args.file:\n        file_path = trestle_root / args.file\n        _, _, model = ModelUtils.load_distributed(file_path, trestle_root)\n        if not self.model_is_valid(model, args.quiet, trestle_root):  # type: ignore\n            logger.info(f'INVALID: Model {file_path} did not pass the {self.error_msg()}')\n            return CmdReturnCodes.OSCAL_VALIDATION_ERROR.value\n        if not args.quiet:\n            logger.info(f'VALID: Model {file_path} passed the {self.error_msg()}')\n    return CmdReturnCodes.SUCCESS.value\n
                                                                            "},{"location":"api_reference/trestle.core.validator_factory/","title":"validator_factory","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory","title":"trestle.core.validator_factory","text":"

                                                                            Register all validators here in the validator_factory.

                                                                            "},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory.validator_factory","title":"validator_factory: ObjectFactory","text":""},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory-functions","title":"Functions","text":""},{"location":"api_reference/trestle.core.validator_factory/#trestle.core.validator_factory.init_arguments","title":"init_arguments(cmd)","text":"

                                                                            Feed the arguments to the argument parser.

                                                                            Source code in trestle/core/validator_factory.py
                                                                            def init_arguments(cmd: Command) -> None:\n\"\"\"Feed the arguments to the argument parser.\"\"\"\n    group = cmd.parser.add_mutually_exclusive_group(required=True)\n    group.add_argument('-f', '--file', help='Path of file in trestle directory to validate.')\n    group.add_argument('-t', '--type', choices=const.MODEL_TYPE_LIST, help='Validate one or all models of this type.')\n    group.add_argument('-a', '--all', action='store_true', help='Validate all models in trestle directory.')\n    cmd.add_argument('-n', '--name', help='Name of single model to validate (with --type specified).', required=False)\n    quiet_help = 'Do not report messages unless validation fails.'\n    cmd.add_argument('-q', '--quiet', action='store_true', help=quiet_help, required=False)\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/","title":"assessment_plan","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan","title":"trestle.oscal.assessment_plan","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan","title":" AssessmentPlan (OscalBaseModel) pydantic-model","text":"

                                                                            An assessment plan, such as those provided by a FedRAMP assessor.

                                                                            Source code in trestle/oscal/assessment_plan.py
                                                                            class AssessmentPlan(OscalBaseModel):\n\"\"\"\n    An assessment plan, such as those provided by a FedRAMP assessor.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment plan in this or other OSCAL instances. The locally defined UUID of the assessment plan can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Plan Universally Unique Identifier',\n    )\n    metadata: common.Metadata\n    import_ssp: common.ImportSsp = Field(..., alias='import-ssp')\n    local_definitions: Optional[LocalDefinitions] = Field(\n        None,\n        alias='local-definitions',\n        description=\n        'Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.',\n        title='Local Definitions'\n    )\n    terms_and_conditions: Optional[TermsAndConditions] = Field(\n        None,\n        alias='terms-and-conditions',\n        description=\n        'Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.',\n        title='Assessment Plan Terms and Conditions'\n    )\n    reviewed_controls: common.ReviewedControls = Field(..., alias='reviewed-controls')\n    assessment_subjects: Optional[List[common.AssessmentSubject]] = Field(None, alias='assessment-subjects')\n    assessment_assets: Optional[common.AssessmentAssets] = Field(None, alias='assessment-assets')\n    tasks: Optional[List[common.Task]] = Field(None)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.assessment_assets","title":"assessment_assets: AssessmentAssets pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.assessment_subjects","title":"assessment_subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.import_ssp","title":"import_ssp: ImportSsp pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.local_definitions","title":"local_definitions: LocalDefinitions pydantic-field","text":"

                                                                            Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.reviewed_controls","title":"reviewed_controls: ReviewedControls pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.terms_and_conditions","title":"terms_and_conditions: TermsAndConditions pydantic-field","text":"

                                                                            Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment plan in this or other OSCAL instances. The locally defined UUID of the assessment plan can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.AssessmentPlan.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_plan.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions","title":" LocalDefinitions (OscalBaseModel) pydantic-model","text":"

                                                                            Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                                                            Source code in trestle/oscal/assessment_plan.py
                                                                            class LocalDefinitions(OscalBaseModel):\n\"\"\"\n    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[common.SystemComponent]] = Field(None)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    users: Optional[List[common.SystemUser]] = Field(None)\n    objectives_and_methods: Optional[List[common.LocalObjective]] = Field(None, alias='objectives-and-methods')\n    activities: Optional[List[common.Activity]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.activities","title":"activities: List[trestle.oscal.common.Activity] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.objectives_and_methods","title":"objectives_and_methods: List[trestle.oscal.common.LocalObjective] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.users","title":"users: List[trestle.oscal.common.SystemUser] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.LocalDefinitions.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_plan.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/assessment_plan.py
                                                                            class Model(OscalBaseModel):\n    assessment_plan: AssessmentPlan = Field(..., alias='assessment-plan')\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.Model.assessment_plan","title":"assessment_plan: AssessmentPlan pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions","title":" TermsAndConditions (OscalBaseModel) pydantic-model","text":"

                                                                            Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.

                                                                            Source code in trestle/oscal/assessment_plan.py
                                                                            class TermsAndConditions(OscalBaseModel):\n\"\"\"\n    Used to define various terms and conditions under which an assessment, described by the plan, can be performed. Each child part defines a different type of term or condition.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    parts: Optional[List[common.AssessmentPart]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.parts","title":"parts: List[trestle.oscal.common.AssessmentPart] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_plan/#trestle.oscal.assessment_plan.TermsAndConditions.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_plan.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/","title":"assessment_results","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results","title":"trestle.oscal.assessment_results","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog","title":" AssessmentLog (OscalBaseModel) pydantic-model","text":"

                                                                            A log of all assessment-related actions taken.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class AssessmentLog(OscalBaseModel):\n\"\"\"\n    A log of all assessment-related actions taken.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    entries: List[Entry1] = Field(...)\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.entries","title":"entries: List[trestle.oscal.assessment_results.Entry1] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentLog.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults","title":" AssessmentResults (OscalBaseModel) pydantic-model","text":"

                                                                            Security assessment results, such as those provided by a FedRAMP assessor in the FedRAMP Security Assessment Report.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class AssessmentResults(OscalBaseModel):\n\"\"\"\n    Security assessment results, such as those provided by a FedRAMP assessor in the FedRAMP Security Assessment Report.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment results instance in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Results Universally Unique Identifier',\n    )\n    metadata: common.Metadata\n    import_ap: ImportAp = Field(..., alias='import-ap')\n    local_definitions: Optional[LocalDefinitions] = Field(\n        None,\n        alias='local-definitions',\n        description=\n        'Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.',\n        title='Local Definitions'\n    )\n    results: List[Result] = Field(...)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.import_ap","title":"import_ap: ImportAp pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.local_definitions","title":"local_definitions: LocalDefinitions pydantic-field","text":"

                                                                            Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.results","title":"results: List[trestle.oscal.assessment_results.Result] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment results instance in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.AssessmentResults.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation","title":" Attestation (OscalBaseModel) pydantic-model","text":"

                                                                            A set of textual statements, typically written by the assessor.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class Attestation(OscalBaseModel):\n\"\"\"\n    A set of textual statements, typically written by the assessor.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    responsible_parties: Optional[List[common.ResponsibleParty]] = Field(None, alias='responsible-parties')\n    parts: List[common.AssessmentPart] = Field(...)\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.parts","title":"parts: List[trestle.oscal.common.AssessmentPart] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Attestation.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1","title":" Entry1 (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the result of an action and/or task that occurred as part of executing an assessment plan or an assessment event that occurred in producing the assessment results.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class Entry1(OscalBaseModel):\n\"\"\"\n    Identifies the result of an action and/or task that occurred as part of executing an assessment plan or an assessment event that occurred in producing the assessment results.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference an assessment event in this or other OSCAL instances. The locally defined UUID of the assessment log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Log Entry Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this event.', title='Action Title')\n    description: Optional[str] = Field(\n        None, description='A human-readable description of this event.', title='Action Description'\n    )\n    start: datetime = Field(..., description='Identifies the start date and time of an event.', title='Start')\n    end: Optional[datetime] = Field(\n        None,\n        description=\n        'Identifies the end date and time of an event. If the event is a point in time, the start and end will be the same date and time.',\n        title='End'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    logged_by: Optional[List[common.LoggedBy]] = Field(None, alias='logged-by')\n    related_tasks: Optional[List[common.RelatedTask]] = Field(None, alias='related-tasks')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of this event.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.end","title":"end: datetime pydantic-field","text":"

                                                                            Identifies the end date and time of an event. If the event is a point in time, the start and end will be the same date and time.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.logged_by","title":"logged_by: List[trestle.oscal.common.LoggedBy] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.related_tasks","title":"related_tasks: List[trestle.oscal.common.RelatedTask] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.start","title":"start: datetime pydantic-field required","text":"

                                                                            Identifies the start date and time of an event.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.title","title":"title: str pydantic-field","text":"

                                                                            The title for this event.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference an assessment event in this or other OSCAL instances. The locally defined UUID of the assessment log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Entry1.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp","title":" ImportAp (OscalBaseModel) pydantic-model","text":"

                                                                            Used by assessment-results to import information about the original plan for assessing the system.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class ImportAp(OscalBaseModel):\n\"\"\"\n    Used by assessment-results to import information about the original plan for assessing the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description='A resolvable URL reference to the assessment plan governing the assessment activities.',\n        title='Assessment Plan Reference'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.href","title":"href: str pydantic-field required","text":"

                                                                            A resolvable URL reference to the assessment plan governing the assessment activities.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.ImportAp.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions","title":" LocalDefinitions (OscalBaseModel) pydantic-model","text":"

                                                                            Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class LocalDefinitions(OscalBaseModel):\n\"\"\"\n    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    objectives_and_methods: Optional[List[common.LocalObjective]] = Field(None, alias='objectives-and-methods')\n    activities: Optional[List[common.Activity]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.activities","title":"activities: List[trestle.oscal.common.Activity] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.objectives_and_methods","title":"objectives_and_methods: List[trestle.oscal.common.LocalObjective] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1","title":" LocalDefinitions1 (OscalBaseModel) pydantic-model","text":"

                                                                            Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class LocalDefinitions1(OscalBaseModel):\n\"\"\"\n    Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[common.SystemComponent]] = Field(None)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    users: Optional[List[common.SystemUser]] = Field(None)\n    assessment_assets: Optional[common.AssessmentAssets] = Field(None, alias='assessment-assets')\n    tasks: Optional[List[common.Task]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.assessment_assets","title":"assessment_assets: AssessmentAssets pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.users","title":"users: List[trestle.oscal.common.SystemUser] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.LocalDefinitions1.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Model(OscalBaseModel):\n    assessment_results: AssessmentResults = Field(..., alias='assessment-results')\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Model.assessment_results","title":"assessment_results: AssessmentResults pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result","title":" Result (OscalBaseModel) pydantic-model","text":"

                                                                            Used by the assessment results and POA&M. In the assessment results, this identifies all of the assessment observations and findings, initial and residual risks, deviations, and disposition. In the POA&M, this identifies initial and residual risks, deviations, and disposition.

                                                                            Source code in trestle/oscal/assessment_results.py
                                                                            class Result(OscalBaseModel):\n\"\"\"\n    Used by the assessment results and POA&M. In the assessment results, this identifies all of the assessment observations and findings, initial and residual risks, deviations, and disposition. In the POA&M, this identifies initial and residual risks, deviations, and disposition.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this set of results in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Results Universally Unique Identifier',\n    )\n    title: str = Field(..., description='The title for this set of results.', title='Results Title')\n    description: str = Field(\n        ..., description='A human-readable description of this set of test results.', title='Results Description'\n    )\n    start: datetime = Field(\n        ...,\n        description='Date/time stamp identifying the start of the evidence collection reflected in these results.',\n        title='start field'\n    )\n    end: Optional[datetime] = Field(\n        None,\n        description=\n        'Date/time stamp identifying the end of the evidence collection reflected in these results. In a continuous motoring scenario, this may contain the same value as start if appropriate.',\n        title='end field'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    local_definitions: Optional[LocalDefinitions1] = Field(\n        None,\n        alias='local-definitions',\n        description=\n        'Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.',\n        title='Local Definitions'\n    )\n    reviewed_controls: common.ReviewedControls = Field(..., alias='reviewed-controls')\n    attestations: Optional[List[Attestation]] = Field(None)\n    assessment_log: Optional[AssessmentLog] = Field(\n        None,\n        alias='assessment-log',\n        description='A log of all assessment-related actions taken.',\n        title='Assessment Log'\n    )\n    observations: Optional[List[common.Observation]] = Field(None)\n    risks: Optional[List[common.Risk]] = Field(None)\n    findings: Optional[List[common.Finding]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.assessment_log","title":"assessment_log: AssessmentLog pydantic-field","text":"

                                                                            A log of all assessment-related actions taken.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.attestations","title":"attestations: List[trestle.oscal.assessment_results.Attestation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this set of test results.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.end","title":"end: datetime pydantic-field","text":"

                                                                            Date/time stamp identifying the end of the evidence collection reflected in these results. In a continuous motoring scenario, this may contain the same value as start if appropriate.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.findings","title":"findings: List[trestle.oscal.common.Finding] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.local_definitions","title":"local_definitions: LocalDefinitions1 pydantic-field","text":"

                                                                            Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.observations","title":"observations: List[trestle.oscal.common.Observation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.reviewed_controls","title":"reviewed_controls: ReviewedControls pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.risks","title":"risks: List[trestle.oscal.common.Risk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.start","title":"start: datetime pydantic-field required","text":"

                                                                            Date/time stamp identifying the start of the evidence collection reflected in these results.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.title","title":"title: str pydantic-field required","text":"

                                                                            The title for this set of results.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this set of results in this or other OSCAL instances. The locally defined UUID of the assessment result can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.assessment_results/#trestle.oscal.assessment_results.Result.Config","title":" Config ","text":"Source code in trestle/oscal/assessment_results.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/","title":"catalog","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog","title":"trestle.oscal.catalog","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog","title":" Catalog (OscalBaseModel) pydantic-model","text":"

                                                                            A structured, organized collection of control information.

                                                                            Source code in trestle/oscal/catalog.py
                                                                            class Catalog(OscalBaseModel):\n\"\"\"\n    A structured, organized collection of control information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given catalog instance.',\n                     title='Catalog Universally Unique Identifier'\n                 )\n    metadata: common.Metadata\n    params: Optional[List[common.Parameter]] = Field(None)\n    controls: Optional[List[Control]] = Field(None)\n    groups: Optional[List[Group]] = Field(None)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.controls","title":"controls: List[trestle.oscal.catalog.Control] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.groups","title":"groups: List[trestle.oscal.catalog.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            Provides a globally unique means to identify a given catalog instance.

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Catalog.Config","title":" Config ","text":"Source code in trestle/oscal/catalog.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control","title":" Control (OscalBaseModel) pydantic-model","text":"

                                                                            A structured object representing a requirement or guideline, which when implemented will reduce an aspect of risk related to an information system and its information.

                                                                            Source code in trestle/oscal/catalog.py
                                                                            class Control(OscalBaseModel):\n\"\"\"\n    A structured object representing a requirement or guideline, which when implemented will reduce an aspect of risk related to an information system and its information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        'Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles).',\n        title='Control Identifier'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a sub-type or characterization of the control.',\n        title='Control Class'\n    )\n    title: str = Field(\n        ...,\n        description='A name given to the control, which may be used by a tool for display and navigation.',\n        title='Control Title'\n    )\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n    controls: Optional[List[Control]] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            A textual label that provides a sub-type or characterization of the control.

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.controls","title":"controls: List[trestle.oscal.catalog.Control] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.id","title":"id: ConstrainedStrValue pydantic-field required","text":"

                                                                            Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles).

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.title","title":"title: str pydantic-field required","text":"

                                                                            A name given to the control, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Control.Config","title":" Config ","text":"Source code in trestle/oscal/catalog.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group","title":" Group (OscalBaseModel) pydantic-model","text":"

                                                                            A group of controls, or of groups of controls.

                                                                            Source code in trestle/oscal/catalog.py
                                                                            class Group(OscalBaseModel):\n\"\"\"\n    A group of controls, or of groups of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        description=\n        'Identifies the group for the purpose of cross-linking within the defining instance or from other instances that reference the catalog.',\n        title='Group Identifier'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a sub-type or characterization of the group.',\n        title='Group Class'\n    )\n    title: str = Field(\n        ...,\n        description='A name given to the group, which may be used by a tool for display and navigation.',\n        title='Group Title'\n    )\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n    groups: Optional[List[Group]] = None\n    controls: Optional[List[Control]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            A textual label that provides a sub-type or characterization of the group.

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.controls","title":"controls: List[trestle.oscal.catalog.Control] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.groups","title":"groups: List[trestle.oscal.catalog.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.id","title":"id: ConstrainedStrValue pydantic-field","text":"

                                                                            Identifies the group for the purpose of cross-linking within the defining instance or from other instances that reference the catalog.

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.title","title":"title: str pydantic-field required","text":"

                                                                            A name given to the group, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Group.Config","title":" Config ","text":"Source code in trestle/oscal/catalog.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/catalog.py
                                                                            class Model(OscalBaseModel):\n    catalog: Catalog\n
                                                                            "},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.catalog/#trestle.oscal.catalog.Model.catalog","title":"catalog: Catalog pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/","title":"common","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common","title":"trestle.oscal.common","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action","title":" Action (OscalBaseModel) pydantic-model","text":"

                                                                            An action applied by a role within a given party to the content.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Action(OscalBaseModel):\n\"\"\"\n    An action applied by a role within a given party to the content.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A unique identifier that can be used to reference this defined action elsewhere in an OSCAL document. A UUID should be consistently used for a given location across revisions of the document.',\n        title='Action Universally Unique Identifier'\n    )\n    date: Optional[datetime] = Field(\n        None, description='The date and time when the action occurred.', title='Action Occurrence Date'\n    )\n    type: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ..., description='The type of action documented by the assembly, such as an approval.', title='Action Type'\n    )\n    system: AnyUrl = Field(..., description='Specifies the action type system used.', title='Action Type System')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.date","title":"date: datetime pydantic-field","text":"

                                                                            The date and time when the action occurred.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.system","title":"system: AnyUrl pydantic-field required","text":"

                                                                            Specifies the action type system used.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.type","title":"type: ConstrainedStrValue pydantic-field required","text":"

                                                                            The type of action documented by the assembly, such as an approval.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A unique identifier that can be used to reference this defined action elsewhere in an OSCAL document. A UUID should be consistently used for a given location across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Action.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity","title":" Activity (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies an assessment or related process that can be performed. In the assessment plan, this is an intended activity which may be associated with an assessment task. In the assessment results, this an activity that was actually performed as part of an assessment.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Activity(OscalBaseModel):\n\"\"\"\n    Identifies an assessment or related process that can be performed. In the assessment plan, this is an intended activity which may be associated with an assessment task. In the assessment results, this an activity that was actually performed as part of an assessment.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment activity elsewhere in this or other OSCAL instances. The locally defined UUID of the activity can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Activity Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(\n        None, description='The title for this included activity.', title='Included Activity Title'\n    )\n    description: str = Field(\n        ...,\n        description='A human-readable description of this included activity.',\n        title='Included Activity Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    steps: Optional[List[Step]] = Field(None)\n    related_controls: Optional[ReviewedControls] = Field(None, alias='related-controls')\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this included activity.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.related_controls","title":"related_controls: ReviewedControls pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.steps","title":"steps: List[trestle.oscal.common.Step] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.title","title":"title: str pydantic-field","text":"

                                                                            The title for this included activity.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment activity elsewhere in this or other OSCAL instances. The locally defined UUID of the activity can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Activity.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine","title":" AddrLine (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class AddrLine(OscalBaseModel):\n    __root__: StringDatatype = Field(..., description='A single line of an address.', title='Address line')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                                                            A single line of an address.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddrLine.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address","title":" Address (OscalBaseModel) pydantic-model","text":"

                                                                            A postal address for the location.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Address(OscalBaseModel):\n\"\"\"\n    A postal address for the location.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: Optional[Union[TokenDatatype, AddressTypeValidValues]] = Field(\n        None, description='Indicates the type of address.', title='Address Type'\n    )\n    addr_lines: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None, alias='addr-lines')\n    city: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='City, town or geographical region for the mailing address.', title='City'\n    )\n    state: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='State, province or analogous geographical region for a mailing address.', title='State'\n    )\n    postal_code: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, alias='postal-code', description='Postal or ZIP code for mailing address.', title='Postal Code'\n    )\n    country: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='The ISO 3166-1 alpha-2 country code for the mailing address.', title='Country Code'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.addr_lines","title":"addr_lines: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.city","title":"city: ConstrainedStrValue pydantic-field","text":"

                                                                            City, town or geographical region for the mailing address.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.country","title":"country: ConstrainedStrValue pydantic-field","text":"

                                                                            The ISO 3166-1 alpha-2 country code for the mailing address.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.postal_code","title":"postal_code: ConstrainedStrValue pydantic-field","text":"

                                                                            Postal or ZIP code for mailing address.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.state","title":"state: ConstrainedStrValue pydantic-field","text":"

                                                                            State, province or analogous geographical region for a mailing address.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.AddressTypeValidValues] pydantic-field","text":"

                                                                            Indicates the type of address.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Address.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddressTypeValidValues","title":" AddressTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class AddressTypeValidValues(Enum):\n    home = 'home'\n    work = 'work'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddressTypeValidValues.home","title":"home","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AddressTypeValidValues.work","title":"work","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm","title":" Algorithm (Enum) ","text":"

                                                                            The digest method by which a hash is derived.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Algorithm(Enum):\n\"\"\"\n    The digest method by which a hash is derived.\n    \"\"\"\n\n    SHA_224 = 'SHA-224'\n    SHA_256 = 'SHA-256'\n    SHA_384 = 'SHA-384'\n    SHA_512 = 'SHA-512'\n    SHA3_224 = 'SHA3-224'\n    SHA3_256 = 'SHA3-256'\n    SHA3_384 = 'SHA3-384'\n    SHA3_512 = 'SHA3-512'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_224","title":"SHA3_224","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_256","title":"SHA3_256","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_384","title":"SHA3_384","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA3_512","title":"SHA3_512","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_224","title":"SHA_224","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_256","title":"SHA_256","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_384","title":"SHA_384","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Algorithm.SHA_512","title":"SHA_512","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets","title":" AssessmentAssets (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the assets used to perform this assessment, such as the assessment team, scanning tools, and assumptions.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AssessmentAssets(OscalBaseModel):\n\"\"\"\n    Identifies the assets used to perform this assessment, such as the assessment team, scanning tools, and assumptions.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[SystemComponent]] = Field(None)\n    assessment_platforms: List[AssessmentPlatform] = Field(..., alias='assessment-platforms')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.assessment_platforms","title":"assessment_platforms: List[trestle.oscal.common.AssessmentPlatform] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentAssets.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart","title":" AssessmentPart (OscalBaseModel) pydantic-model","text":"

                                                                            A partition of an assessment plan or results or a child of another part.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AssessmentPart(OscalBaseModel):\n\"\"\"\n    A partition of an assessment plan or results or a child of another part.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this part elsewhere in this or other OSCAL instances. The locally defined UUID of the part can be used to reference the data item locally or globally (e.g., in an ported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Part Identifier'\n    )\n    name: Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                Name] = Field(\n                    ...,\n                    description=\"A textual label that uniquely identifies the part's semantic type.\",\n                    title='Part Name'\n                )\n    ns: Optional[AnyUrl] = Field(\n        None,\n        description=\n        \"A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.\",\n        title='Part Namespace'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\n        \"A textual label that provides a sub-type or characterization of the part's name. This can be used to further distinguish or discriminate between the semantics of multiple parts of the same control with the same name and ns.\",\n        title='Part Class'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the part, which may be used by a tool for display and navigation.',\n        title='Part Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    prose: Optional[str] = Field(None, description='Permits multiple paragraphs, lists, tables etc.', title='Part Text')\n    parts: Optional[List[AssessmentPart]] = None\n    links: Optional[List[Link]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            A textual label that provides a sub-type or characterization of the part's name. This can be used to further distinguish or discriminate between the semantics of multiple parts of the same control with the same name and ns.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.name","title":"name: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Name] pydantic-field required","text":"

                                                                            A textual label that uniquely identifies the part's semantic type.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.ns","title":"ns: AnyUrl pydantic-field","text":"

                                                                            A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.parts","title":"parts: List[trestle.oscal.common.AssessmentPart] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.prose","title":"prose: str pydantic-field","text":"

                                                                            Permits multiple paragraphs, lists, tables etc.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.title","title":"title: str pydantic-field","text":"

                                                                            A name given to the part, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this part elsewhere in this or other OSCAL instances. The locally defined UUID of the part can be used to reference the data item locally or globally (e.g., in an ported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPart.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform","title":" AssessmentPlatform (OscalBaseModel) pydantic-model","text":"

                                                                            Used to represent the toolset used to perform aspects of the assessment.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AssessmentPlatform(OscalBaseModel):\n\"\"\"\n    Used to represent the toolset used to perform aspects of the assessment.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment platform elsewhere in this or other OSCAL instances. The locally defined UUID of the assessment platform can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Platform Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(\n        None, description='The title or name for the assessment platform.', title='Assessment Platform Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    uses_components: Optional[List[UsesComponent]] = Field(None, alias='uses-components')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.title","title":"title: str pydantic-field","text":"

                                                                            The title or name for the assessment platform.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.uses_components","title":"uses_components: List[trestle.oscal.common.UsesComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this assessment platform elsewhere in this or other OSCAL instances. The locally defined UUID of the assessment platform can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentPlatform.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject","title":" AssessmentSubject (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies system elements being assessed, such as components, inventory items, and locations. In the assessment plan, this identifies a planned assessment subject. In the assessment results this is an actual assessment subject, and reflects any changes from the plan. exactly what will be the focus of this assessment. Any subjects not identified in this way are out-of-scope.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AssessmentSubject(OscalBaseModel):\n\"\"\"\n    Identifies system elements being assessed, such as components, inventory items, and locations. In the assessment plan, this identifies a planned assessment subject. In the assessment results this is an actual assessment subject, and reflects any changes from the plan. exactly what will be the focus of this assessment. Any subjects not identified in this way are out-of-scope.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: Union[TokenDatatype, AssessmentSubjectValidValues] = Field(\n        ...,\n        description=\n        'Indicates the type of assessment subject, such as a component, inventory, item, location, or party represented by this selection statement.',\n        title='Subject Type'\n    )\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of the collection of subjects being included in this assessment.',\n        title='Include Subjects Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    include_all: Optional[IncludeAll] = Field(None, alias='include-all')\n    include_subjects: Optional[List[SelectSubjectById]] = Field(None, alias='include-subjects')\n    exclude_subjects: Optional[List[SelectSubjectById]] = Field(None, alias='exclude-subjects')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of the collection of subjects being included in this assessment.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.exclude_subjects","title":"exclude_subjects: List[trestle.oscal.common.SelectSubjectById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.include_subjects","title":"include_subjects: List[trestle.oscal.common.SelectSubjectById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.AssessmentSubjectValidValues] pydantic-field required","text":"

                                                                            Indicates the type of assessment subject, such as a component, inventory, item, location, or party represented by this selection statement.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubject.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder","title":" AssessmentSubjectPlaceholder (OscalBaseModel) pydantic-model","text":"

                                                                            Used when the assessment subjects will be determined as part of one or more other assessment activities. These assessment subjects will be recorded in the assessment results in the assessment log.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AssessmentSubjectPlaceholder(OscalBaseModel):\n\"\"\"\n    Used when the assessment subjects will be determined as part of one or more other assessment activities. These assessment subjects will be recorded in the assessment results in the assessment log.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier for a set of assessment subjects that will be identified by a task or an activity that is part of a task. The locally defined UUID of the assessment subject placeholder can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Assessment Subject Placeholder Universally Unique Identifier',\n    )\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of intent of this assessment subject placeholder.',\n        title='Assessment Subject Placeholder Description'\n    )\n    sources: List[Source] = Field(...)\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of intent of this assessment subject placeholder.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.sources","title":"sources: List[trestle.oscal.common.Source] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier for a set of assessment subjects that will be identified by a task or an activity that is part of a task. The locally defined UUID of the assessment subject placeholder can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectPlaceholder.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues","title":" AssessmentSubjectValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class AssessmentSubjectValidValues(Enum):\n    component = 'component'\n    inventory_item = 'inventory-item'\n    location = 'location'\n    party = 'party'\n    user = 'user'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.component","title":"component","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.inventory_item","title":"inventory_item","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.location","title":"location","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssessmentSubjectValidValues.user","title":"user","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity","title":" AssociatedActivity (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies an individual activity to be performed as part of a task.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AssociatedActivity(OscalBaseModel):\n\"\"\"\n    Identifies an individual activity to be performed as part of a task.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    activity_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='activity-uuid',\n        description='A machine-oriented identifier reference to an activity defined in the list of activities.',\n        title='Activity Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    subjects: List[AssessmentSubject] = Field(...)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.activity_uuid","title":"activity_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to an activity defined in the list of activities.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AssociatedActivity.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency","title":" AtFrequency (OscalBaseModel) pydantic-model","text":"

                                                                            The task is intended to occur at the specified frequency.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AtFrequency(OscalBaseModel):\n\"\"\"\n    The task is intended to occur at the specified frequency.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    period: conint(\n        ge=1, multiple_of=1\n    ) = Field(..., description='The task must occur after the specified period has elapsed.', title='Period')\n    unit: TimeUnitValidValues = Field(..., description='The unit of time for the period.', title='Time Unit')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.period","title":"period: ConstrainedIntValue pydantic-field required","text":"

                                                                            The task must occur after the specified period has elapsed.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.unit","title":"unit: TimeUnitValidValues pydantic-field required","text":"

                                                                            The unit of time for the period.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AtFrequency.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege","title":" AuthorizedPrivilege (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies a specific system privilege held by the user, along with an associated description and/or rationale for the privilege.

                                                                            Source code in trestle/oscal/common.py
                                                                            class AuthorizedPrivilege(OscalBaseModel):\n\"\"\"\n    Identifies a specific system privilege held by the user, along with an associated description and/or rationale for the privilege.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    title: str = Field(..., description='A human readable name for the privilege.', title='Privilege Title')\n    description: Optional[str] = Field(\n        None, description=\"A summary of the privilege's purpose within the system.\", title='Privilege Description'\n    )\n    functions_performed: List[constr(regex=r'^\\S(.*\\S)?$')] = Field(..., alias='functions-performed')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.description","title":"description: str pydantic-field","text":"

                                                                            A summary of the privilege's purpose within the system.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.functions_performed","title":"functions_performed: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.title","title":"title: str pydantic-field required","text":"

                                                                            A human readable name for the privilege.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.AuthorizedPrivilege.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter","title":" BackMatter (OscalBaseModel) pydantic-model","text":"

                                                                            A collection of resources that may be referenced from within the OSCAL document instance.

                                                                            Source code in trestle/oscal/common.py
                                                                            class BackMatter(OscalBaseModel):\n\"\"\"\n    A collection of resources that may be referenced from within the OSCAL document instance.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    resources: Optional[List[Resource]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.resources","title":"resources: List[trestle.oscal.common.Resource] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.BackMatter.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64","title":" Base64 (OscalBaseModel) pydantic-model","text":"

                                                                            A resource encoded using the Base64 alphabet defined by RFC 2045.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Base64(OscalBaseModel):\n\"\"\"\n    A resource encoded using the Base64 alphabet defined by RFC 2045.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    filename: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        description=\n        'Name of the file before it was encoded as Base64 to be embedded in a resource. This is the name that will be assigned to the file when the file is decoded.',\n        title='File Name'\n    )\n    media_type: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='media-type',\n        description='A label that indicates the nature of a resource, as a data serialization or format.',\n        title='Media Type'\n    )\n    value: constr(regex=r'^[0-9A-Za-z+/]+={0,2}$')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.filename","title":"filename: ConstrainedStrValue pydantic-field","text":"

                                                                            Name of the file before it was encoded as Base64 to be embedded in a resource. This is the name that will be assigned to the file when the file is decoded.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.media_type","title":"media_type: ConstrainedStrValue pydantic-field","text":"

                                                                            A label that indicates the nature of a resource, as a data serialization or format.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.value","title":"value: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype","title":" Base64Datatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class Base64Datatype(OscalBaseModel):\n    __root__: constr(\n        regex=r'^[0-9A-Za-z+/]+={0,2}$'\n    ) = Field(..., description='Binary data encoded using the Base 64 encoding algorithm as defined by RFC4648.')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            Binary data encoded using the Base 64 encoding algorithm as defined by RFC4648.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Base64Datatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization","title":" Characterization (OscalBaseModel) pydantic-model","text":"

                                                                            A collection of descriptive data about the containing object from a specific origin.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Characterization(OscalBaseModel):\n\"\"\"\n    A collection of descriptive data about the containing object from a specific origin.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    origin: Origin\n    facets: List[Facet] = Field(...)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.facets","title":"facets: List[trestle.oscal.common.Facet] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.origin","title":"origin: Origin pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Characterization.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation","title":" Citation (OscalBaseModel) pydantic-model","text":"

                                                                            An optional citation consisting of end note text using structured markup.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Citation(OscalBaseModel):\n\"\"\"\n    An optional citation consisting of end note text using structured markup.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    text: str = Field(..., description='A line of citation text.', title='Citation Text')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.text","title":"text: str pydantic-field required","text":"

                                                                            A line of citation text.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Citation.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection","title":" ControlObjectiveSelection (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the control objectives of the assessment. In the assessment plan, these are the planned objectives. In the assessment results, these are the assessed objectives, and reflects any changes from the plan.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ControlObjectiveSelection(OscalBaseModel):\n\"\"\"\n    Identifies the control objectives of the assessment. In the assessment plan, these are the planned objectives. In the assessment results, these are the assessed objectives, and reflects any changes from the plan.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of this collection of control objectives.',\n        title='Control Objectives Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    include_all: Optional[IncludeAll] = Field(None, alias='include-all')\n    include_objectives: Optional[List[SelectObjectiveById]] = Field(None, alias='include-objectives')\n    exclude_objectives: Optional[List[SelectObjectiveById]] = Field(None, alias='exclude-objectives')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of this collection of control objectives.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.exclude_objectives","title":"exclude_objectives: List[trestle.oscal.common.SelectObjectiveById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.include_objectives","title":"include_objectives: List[trestle.oscal.common.SelectObjectiveById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlObjectiveSelection.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection","title":" ControlSelection (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the controls being assessed. In the assessment plan, these are the planned controls. In the assessment results, these are the actual controls, and reflects any changes from the plan.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ControlSelection(OscalBaseModel):\n\"\"\"\n    Identifies the controls being assessed. In the assessment plan, these are the planned controls. In the assessment results, these are the actual controls, and reflects any changes from the plan.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of in-scope controls specified for assessment.',\n        title='Assessed Controls Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    include_all: Optional[IncludeAll] = Field(None, alias='include-all')\n    include_controls: Optional[List[SelectControlById]] = Field(None, alias='include-controls')\n    exclude_controls: Optional[List[SelectControlById]] = Field(None, alias='exclude-controls')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of in-scope controls specified for assessment.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.exclude_controls","title":"exclude_controls: List[trestle.oscal.common.SelectControlById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.include_controls","title":"include_controls: List[trestle.oscal.common.SelectControlById] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ControlSelection.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype","title":" DateTimeWithTimezoneDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class DateTimeWithTimezoneDatatype(OscalBaseModel):\n    __root__: datetime = Field(..., description='A string representing a point in time with a required timezone.')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__root__","title":"__root__: datetime pydantic-field required special","text":"

                                                                            A string representing a point in time with a required timezone.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DateTimeWithTimezoneDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency","title":" Dependency (OscalBaseModel) pydantic-model","text":"

                                                                            Used to indicate that a task is dependent on another task.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Dependency(OscalBaseModel):\n\"\"\"\n    Used to indicate that a task is dependent on another task.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    task_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='task-uuid',\n        description='A machine-oriented identifier reference to a unique task.',\n        title='Task Universally Unique Identifier Reference'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.task_uuid","title":"task_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a unique task.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Dependency.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId","title":" DocumentId (OscalBaseModel) pydantic-model","text":"

                                                                            A document identifier qualified by an identifier scheme.

                                                                            Source code in trestle/oscal/common.py
                                                                            class DocumentId(OscalBaseModel):\n\"\"\"\n    A document identifier qualified by an identifier scheme.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    scheme: Optional[Union[URIDatatype, DocumentSchemeValidValues]] = Field(\n        None,\n        description=\n        'Qualifies the kind of document identifier using a URI. If the scheme is not provided the value of the element will be interpreted as a string of characters.',\n        title='Document Identification Scheme'\n    )\n    identifier: constr(regex=r'^\\S(.*\\S)?$')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.identifier","title":"identifier: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.scheme","title":"scheme: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.DocumentSchemeValidValues] pydantic-field","text":"

                                                                            Qualifies the kind of document identifier using a URI. If the scheme is not provided the value of the element will be interpreted as a string of characters.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.DocumentSchemeValidValues","title":" DocumentSchemeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class DocumentSchemeValidValues(Enum):\n    http___www_doi_org_ = 'http://www.doi.org/'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress","title":" EmailAddress (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class EmailAddress(OscalBaseModel):\n    __root__: EmailStr = Field(\n        ..., description='An email address as defined by RFC 5322 Section 3.4.1.', title='Email Address'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__root__","title":"__root__: EmailStr pydantic-field required special","text":"

                                                                            An email address as defined by RFC 5322 Section 3.4.1.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddress.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype","title":" EmailAddressDatatype (OscalBaseModel) pydantic-model","text":"

                                                                            An email address string formatted according to RFC 6531.

                                                                            Source code in trestle/oscal/common.py
                                                                            class EmailAddressDatatype(OscalBaseModel):\n\"\"\"\n    An email address string formatted according to RFC 6531.\n    \"\"\"\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.EmailAddressDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry","title":" Entry (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies an individual risk response that occurred as part of managing an identified risk.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Entry(OscalBaseModel):\n\"\"\"\n    Identifies an individual risk response that occurred as part of managing an identified risk.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk log entry elsewhere in this or other OSCAL instances. The locally defined UUID of the risk log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Risk Log Entry Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this risk log entry.', title='Title')\n    description: Optional[str] = Field(\n        None,\n        description='A human-readable description of what was done regarding the risk.',\n        title='Risk Task Description'\n    )\n    start: datetime = Field(..., description='Identifies the start date and time of the event.', title='Start')\n    end: Optional[datetime] = Field(\n        None,\n        description=\n        'Identifies the end date and time of the event. If the event is a point in time, the start and end will be the same date and time.',\n        title='End'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    logged_by: Optional[List[LoggedBy]] = Field(None, alias='logged-by')\n    status_change: Optional[RiskStatus] = Field(None, alias='status-change')\n    related_responses: Optional[List[RelatedResponse]] = Field(None, alias='related-responses')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of what was done regarding the risk.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.end","title":"end: datetime pydantic-field","text":"

                                                                            Identifies the end date and time of the event. If the event is a point in time, the start and end will be the same date and time.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.logged_by","title":"logged_by: List[trestle.oscal.common.LoggedBy] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.related_responses","title":"related_responses: List[trestle.oscal.common.RelatedResponse] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.start","title":"start: datetime pydantic-field required","text":"

                                                                            Identifies the start date and time of the event.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.status_change","title":"status_change: RiskStatus pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.title","title":"title: str pydantic-field","text":"

                                                                            The title for this risk log entry.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk log entry elsewhere in this or other OSCAL instances. The locally defined UUID of the risk log entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Entry.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId","title":" ExternalId (OscalBaseModel) pydantic-model","text":"

                                                                            An identifier for a person or organization using a designated scheme. e.g. an Open Researcher and Contributor ID (ORCID).

                                                                            Source code in trestle/oscal/common.py
                                                                            class ExternalId(OscalBaseModel):\n\"\"\"\n    An identifier for a person or organization using a designated scheme. e.g. an Open Researcher and Contributor ID (ORCID).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    scheme: Union[URIDatatype, ExternalSchemeValidValues] = Field(\n        ..., description='Indicates the type of external identifier.', title='External Identifier Schema'\n    )\n    id: constr(regex=r'^\\S(.*\\S)?$')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.id","title":"id: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.scheme","title":"scheme: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.ExternalSchemeValidValues] pydantic-field required","text":"

                                                                            Indicates the type of external identifier.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ExternalSchemeValidValues","title":" ExternalSchemeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class ExternalSchemeValidValues(Enum):\n    http___orcid_org_ = 'http://orcid.org/'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet","title":" Facet (OscalBaseModel) pydantic-model","text":"

                                                                            An individual characteristic that is part of a larger set produced by the same actor.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Facet(OscalBaseModel):\n\"\"\"\n    An individual characteristic that is part of a larger set produced by the same actor.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    name: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., description='The name of the risk metric within the specified system.', title='Facet Name')\n    system: Union[URIDatatype, NamingSystemValidValues] = Field(\n        ...,\n        description=\n        'Specifies the naming system under which this risk metric is organized, which allows for the same names to be used in different systems controlled by different parties. This avoids the potential of a name clash.',\n        title='Naming System'\n    )\n    value: constr(regex=r'^\\S(.*\\S)?$'\n                  ) = Field(..., description='Indicates the value of the facet.', title='Facet Value')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                                                            The name of the risk metric within the specified system.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.system","title":"system: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.NamingSystemValidValues] pydantic-field required","text":"

                                                                            Specifies the naming system under which this risk metric is organized, which allows for the same names to be used in different systems controlled by different parties. This avoids the potential of a name clash.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.value","title":"value: ConstrainedStrValue pydantic-field required","text":"

                                                                            Indicates the value of the facet.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Facet.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding","title":" Finding (OscalBaseModel) pydantic-model","text":"

                                                                            Describes an individual finding.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Finding(OscalBaseModel):\n\"\"\"\n    Describes an individual finding.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this finding in this or other OSCAL instances. The locally defined UUID of the finding can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Finding Universally Unique Identifier',\n    )\n    title: str = Field(..., description='The title for this finding.', title='Finding Title')\n    description: str = Field(\n        ..., description='A human-readable description of this finding.', title='Finding Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    origins: Optional[List[Origin]] = Field(None)\n    target: FindingTarget\n    implementation_statement_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='implementation-statement-uuid',\n        description=\n        'A machine-oriented identifier reference to the implementation statement in the SSP to which this finding is related.',\n        title='Implementation Statement UUID'\n    )\n    related_observations: Optional[List[RelatedObservation]] = Field(None, alias='related-observations')\n    related_risks: Optional[List[RelatedRisk]] = Field(None, alias='related-risks')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this finding.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.implementation_statement_uuid","title":"implementation_statement_uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented identifier reference to the implementation statement in the SSP to which this finding is related.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.related_observations","title":"related_observations: List[trestle.oscal.common.RelatedObservation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.related_risks","title":"related_risks: List[trestle.oscal.common.RelatedRisk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.target","title":"target: FindingTarget pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.title","title":"title: str pydantic-field required","text":"

                                                                            The title for this finding.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this finding in this or other OSCAL instances. The locally defined UUID of the finding can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Finding.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget","title":" FindingTarget (OscalBaseModel) pydantic-model","text":"

                                                                            Captures an assessor's conclusions regarding the degree to which an objective is satisfied.

                                                                            Source code in trestle/oscal/common.py
                                                                            class FindingTarget(OscalBaseModel):\n\"\"\"\n    Captures an assessor's conclusions regarding the degree to which an objective is satisfied.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: FindingTargetTypeValidValues = Field(\n        ..., description='Identifies the type of the target.', title='Finding Target Type'\n    )\n    target_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='target-id',\n        description='A machine-oriented identifier reference for a specific target qualified by the type.',\n        title='Finding Target Identifier Reference'\n    )\n    title: Optional[str] = Field(\n        None, description='The title for this objective status.', title='Objective Status Title'\n    )\n    description: Optional[str] = Field(\n        None,\n        description=\n        \"A human-readable description of the assessor's conclusions regarding the degree to which an objective is satisfied.\",\n        title='Objective Status Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    implementation_status: Optional[ImplementationStatus] = Field(None, alias='implementation-status')\n    remarks: Optional[str] = None\n    status: Optional[ObjectiveStatus] = Field(\n        None,\n        description='A determination of if the objective is satisfied or not within a given system.',\n        title='Objective Status'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of the assessor's conclusions regarding the degree to which an objective is satisfied.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.implementation_status","title":"implementation_status: ImplementationStatus pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.status","title":"status: ObjectiveStatus pydantic-field","text":"

                                                                            A determination of if the objective is satisfied or not within a given system.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.target_id","title":"target_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference for a specific target qualified by the type.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.title","title":"title: str pydantic-field","text":"

                                                                            The title for this objective status.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.type","title":"type: FindingTargetTypeValidValues pydantic-field required","text":"

                                                                            Identifies the type of the target.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTarget.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTargetTypeValidValues","title":" FindingTargetTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class FindingTargetTypeValidValues(Enum):\n    statement_id = 'statement-id'\n    objective_id = 'objective-id'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTargetTypeValidValues.objective_id","title":"objective_id","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FindingTargetTypeValidValues.statement_id","title":"statement_id","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed","title":" FunctionPerformed (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class FunctionPerformed(OscalBaseModel):\n    __root__: StringDatatype = Field(\n        ...,\n        description='Describes a function performed for a given authorized privilege by this user class.',\n        title='Functions Performed'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                                                            Describes a function performed for a given authorized privilege by this user class.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.FunctionPerformed.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash","title":" Hash (OscalBaseModel) pydantic-model","text":"

                                                                            A representation of a cryptographic digest generated over a resource using a specified hash algorithm.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Hash(OscalBaseModel):\n\"\"\"\n    A representation of a cryptographic digest generated over a resource using a specified hash algorithm.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    algorithm: Union[constr(regex=r'^\\S(.*\\S)?$'), Algorithm] = Field(\n        ..., description='The digest method by which a hash is derived.', title='Hash algorithm'\n    )\n    value: constr(regex=r'^\\S(.*\\S)?$')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.algorithm","title":"algorithm: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Algorithm] pydantic-field required","text":"

                                                                            The digest method by which a hash is derived.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.value","title":"value: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Hash.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowMany","title":" HowMany (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class HowManyValidValues(Enum):\n    one = 'one'\n    one_or_more = 'one-or-more'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowMany.one","title":"one","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowMany.one_or_more","title":"one_or_more","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowManyValidValues","title":" HowManyValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class HowManyValidValues(Enum):\n    one = 'one'\n    one_or_more = 'one-or-more'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowManyValidValues.one","title":"one","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.HowManyValidValues.one_or_more","title":"one_or_more","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject","title":" IdentifiedSubject (OscalBaseModel) pydantic-model","text":"

                                                                            Used to detail assessment subjects that were identfied by this task.

                                                                            Source code in trestle/oscal/common.py
                                                                            class IdentifiedSubject(OscalBaseModel):\n\"\"\"\n    Used to detail assessment subjects that were identfied by this task.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    subject_placeholder_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='subject-placeholder-uuid',\n        description=\n        'A machine-oriented identifier reference to a unique assessment subject placeholder defined by this task.',\n        title='Assessment Subject Placeholder Universally Unique Identifier Reference'\n    )\n    subjects: List[AssessmentSubject] = Field(...)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.subject_placeholder_uuid","title":"subject_placeholder_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a unique assessment subject placeholder defined by this task.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifiedSubject.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType","title":" IdentifierType (Enum) ","text":"

                                                                            Identifies the identification system from which the provided identifier was assigned.

                                                                            Source code in trestle/oscal/common.py
                                                                            class IdentifierType(Enum):\n\"\"\"\n    Identifies the identification system from which the provided identifier was assigned.\n    \"\"\"\n\n    https___fedramp_gov = 'https://fedramp.gov'\n    http___fedramp_gov_ns_oscal = 'http://fedramp.gov/ns/oscal'\n    https___ietf_org_rfc_rfc4122 = 'https://ietf.org/rfc/rfc4122'\n    http___ietf_org_rfc_rfc4122 = 'http://ietf.org/rfc/rfc4122'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.http___fedramp_gov_ns_oscal","title":"http___fedramp_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.http___ietf_org_rfc_rfc4122","title":"http___ietf_org_rfc_rfc4122","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.https___fedramp_gov","title":"https___fedramp_gov","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IdentifierType.https___ietf_org_rfc_rfc4122","title":"https___ietf_org_rfc_rfc4122","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus","title":" ImplementationStatus (OscalBaseModel) pydantic-model","text":"

                                                                            Indicates the degree to which the a given control is implemented.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ImplementationStatus(OscalBaseModel):\n\"\"\"\n    Indicates the degree to which the a given control is implemented.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                 State] = Field(\n                     ...,\n                     description='Identifies the implementation status of the control or control objective.',\n                     title='Implementation State'\n                 )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.state","title":"state: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.State] pydantic-field required","text":"

                                                                            Identifies the implementation status of the control or control objective.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementationStatus.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent","title":" ImplementedComponent (OscalBaseModel) pydantic-model","text":"

                                                                            The set of components that are implemented in a given system inventory item.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ImplementedComponent(OscalBaseModel):\n\"\"\"\n    The set of components that are implemented in a given system inventory item.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description=\n        'A machine-oriented identifier reference to a component that is implemented as part of an inventory item.',\n        title='Component Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a component that is implemented as part of an inventory item.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImplementedComponent.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp","title":" ImportSsp (OscalBaseModel) pydantic-model","text":"

                                                                            Used by the assessment plan and POA&M to import information about the system.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ImportSsp(OscalBaseModel):\n\"\"\"\n    Used by the assessment plan and POA&M to import information about the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description='A resolvable URL reference to the system security plan for the system being assessed.',\n        title='System Security Plan Reference'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.href","title":"href: str pydantic-field required","text":"

                                                                            A resolvable URL reference to the system security plan for the system being assessed.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ImportSsp.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll","title":" IncludeAll (OscalBaseModel) pydantic-model","text":"

                                                                            Include all controls from the imported catalog or profile resources.

                                                                            Source code in trestle/oscal/common.py
                                                                            class IncludeAll(OscalBaseModel):\n\"\"\"\n    Include all controls from the imported catalog or profile resources.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IncludeAll.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype","title":" IntegerDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class IntegerDatatype(OscalBaseModel):\n    __root__: int = Field(..., description='A whole number value.')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__root__","title":"__root__: int pydantic-field required special","text":"

                                                                            A whole number value.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.IntegerDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem","title":" InventoryItem (OscalBaseModel) pydantic-model","text":"

                                                                            A single managed inventory item within the system.

                                                                            Source code in trestle/oscal/common.py
                                                                            class InventoryItem(OscalBaseModel):\n\"\"\"\n    A single managed inventory item within the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inventory item elsewhere in this or other OSCAL instances. The locally defined UUID of the inventory item can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Inventory Item Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description='A summary of the inventory item stating its purpose within the system.',\n        title='Inventory Item Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    implemented_components: Optional[List[ImplementedComponent]] = Field(None, alias='implemented-components')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of the inventory item stating its purpose within the system.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.implemented_components","title":"implemented_components: List[trestle.oscal.common.ImplementedComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inventory item elsewhere in this or other OSCAL instances. The locally defined UUID of the inventory item can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.InventoryItem.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective","title":" JsonSchemaDirective (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class JsonSchemaDirective(OscalBaseModel):\n    __root__: URIReferenceDatatype = Field(\n        ...,\n        description='A JSON Schema directive to bind a specific schema to its document instance.',\n        title='Schema Directive'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__root__","title":"__root__: URIReferenceDatatype pydantic-field required special","text":"

                                                                            A JSON Schema directive to bind a specific schema to its document instance.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.JsonSchemaDirective.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified","title":" LastModified (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class LastModified(OscalBaseModel):\n    __root__: DateTimeWithTimezoneDatatype = Field(\n        ...,\n        description='The date and time the document was last stored for later retrieval.',\n        title='Last Modified Timestamp'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__root__","title":"__root__: DateTimeWithTimezoneDatatype pydantic-field required special","text":"

                                                                            The date and time the document was last stored for later retrieval.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LastModified.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle","title":" Lifecycle (Enum) ","text":"

                                                                            Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Lifecycle(Enum):\n\"\"\"\n    Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.\n    \"\"\"\n\n    recommendation = 'recommendation'\n    planned = 'planned'\n    completed = 'completed'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle.completed","title":"completed","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle.planned","title":"planned","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Lifecycle.recommendation","title":"recommendation","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link","title":" Link (OscalBaseModel) pydantic-model","text":"

                                                                            A reference to a local or remote resource, that has a specific relation to the containing object.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Link(OscalBaseModel):\n\"\"\"\n    A reference to a local or remote resource, that has a specific relation to the containing object.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(..., description='A resolvable URL reference to a resource.', title='Hypertext Reference')\n    rel: Optional[\n        Union[constr(\n            regex=\n            r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n        ),\n              Rel]\n    ] = Field(\n        None,\n        description=\n        \"Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.\",\n        title='Link Relation Type'\n    )\n    media_type: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='media-type',\n        description='A label that indicates the nature of a resource, as a data serialization or format.',\n        title='Media Type'\n    )\n    resource_fragment: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='resource-fragment',\n        description=\n        'In case where the href points to a back-matter/resource, this value will indicate the URI fragment to append to any rlink associated with the resource. This value MUST be URI encoded.',\n        title='Resource Fragment'\n    )\n    text: Optional[str] = Field(\n        None,\n        description='A textual label to associate with the link, which may be used for presentation in a tool.',\n        title='Link Text'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.href","title":"href: str pydantic-field required","text":"

                                                                            A resolvable URL reference to a resource.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.media_type","title":"media_type: ConstrainedStrValue pydantic-field","text":"

                                                                            A label that indicates the nature of a resource, as a data serialization or format.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.rel","title":"rel: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Rel] pydantic-field","text":"

                                                                            Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.resource_fragment","title":"resource_fragment: ConstrainedStrValue pydantic-field","text":"

                                                                            In case where the href points to a back-matter/resource, this value will indicate the URI fragment to append to any rlink associated with the resource. This value MUST be URI encoded.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.text","title":"text: str pydantic-field","text":"

                                                                            A textual label to associate with the link, which may be used for presentation in a tool.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Link.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective","title":" LocalObjective (OscalBaseModel) pydantic-model","text":"

                                                                            A local definition of a control objective for this assessment. Uses catalog syntax for control objective and assessment actions.

                                                                            Source code in trestle/oscal/common.py
                                                                            class LocalObjective(OscalBaseModel):\n\"\"\"\n    A local definition of a control objective for this assessment. Uses catalog syntax for control objective and assessment actions.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    description: Optional[str] = Field(\n        None, description='A human-readable description of this control objective.', title='Objective Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    parts: List[Part] = Field(...)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of this control objective.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocalObjective.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location","title":" Location (OscalBaseModel) pydantic-model","text":"

                                                                            A physical point of presence, which may be associated with people, organizations, or other concepts within the current or linked OSCAL document.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Location(OscalBaseModel):\n\"\"\"\n    A physical point of presence, which may be associated with people, organizations, or other concepts within the current or linked OSCAL document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='A unique ID for the location, for reference.',\n                     title='Location Universally Unique Identifier'\n                 )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the location, which may be used by a tool for display and navigation.',\n        title='Location Title'\n    )\n    address: Optional[Address] = None\n    email_addresses: Optional[List[EmailAddress]] = Field(None, alias='email-addresses')\n    telephone_numbers: Optional[List[TelephoneNumber]] = Field(None, alias='telephone-numbers')\n    urls: Optional[List[AnyUrl]] = Field(None)\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.address","title":"address: Address pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.email_addresses","title":"email_addresses: List[trestle.oscal.common.EmailAddress] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.telephone_numbers","title":"telephone_numbers: List[trestle.oscal.common.TelephoneNumber] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.title","title":"title: str pydantic-field","text":"

                                                                            A name given to the location, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.urls","title":"urls: List[pydantic.v1.networks.AnyUrl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A unique ID for the location, for reference.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Location.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid","title":" LocationUuid (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class LocationUuid(OscalBaseModel):\n    __root__: UUIDDatatype = Field(\n        ..., description='Reference to a location by UUID.', title='Location Universally Unique Identifier Reference'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__root__","title":"__root__: UUIDDatatype pydantic-field required special","text":"

                                                                            Reference to a location by UUID.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LocationUuid.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy","title":" LoggedBy (OscalBaseModel) pydantic-model","text":"

                                                                            Used to indicate who created a log entry in what role.

                                                                            Source code in trestle/oscal/common.py
                                                                            class LoggedBy(OscalBaseModel):\n\"\"\"\n    Used to indicate who created a log entry in what role.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    party_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='party-uuid',\n        description='A machine-oriented identifier reference to the party who is making the log entry.',\n        title='Party UUID Reference'\n    )\n    role_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='role-id',\n        description='A point to the role-id of the role in which the party is making the log entry.',\n        title='Actor Role'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.party_uuid","title":"party_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to the party who is making the log entry.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.role_id","title":"role_id: ConstrainedStrValue pydantic-field","text":"

                                                                            A point to the role-id of the role in which the party is making the log entry.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.LoggedBy.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata","title":" Metadata (OscalBaseModel) pydantic-model","text":"

                                                                            Provides information about the containing document, and defines concepts that are shared across the document.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Metadata(OscalBaseModel):\n\"\"\"\n    Provides information about the containing document, and defines concepts that are shared across the document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    title: str = Field(\n        ...,\n        description='A name given to the document, which may be used by a tool for display and navigation.',\n        title='Document Title'\n    )\n    published: Optional[datetime] = None\n    last_modified: datetime = Field(..., alias='last-modified')\n    version: constr(regex=r'^\\S(.*\\S)?$')\n    oscal_version: OscalVersion = Field(..., alias='oscal-version')\n    revisions: Optional[List[Revision]] = Field(None)\n    document_ids: Optional[List[DocumentId]] = Field(None, alias='document-ids')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    roles: Optional[List[Role]] = Field(None)\n    locations: Optional[List[Location]] = Field(None)\n    parties: Optional[List[Party]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    actions: Optional[List[Action]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.actions","title":"actions: List[trestle.oscal.common.Action] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.document_ids","title":"document_ids: List[trestle.oscal.common.DocumentId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.last_modified","title":"last_modified: datetime pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.locations","title":"locations: List[trestle.oscal.common.Location] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.oscal_version","title":"oscal_version: OscalVersion pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.parties","title":"parties: List[trestle.oscal.common.Party] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.published","title":"published: datetime pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.revisions","title":"revisions: List[trestle.oscal.common.Revision] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.roles","title":"roles: List[trestle.oscal.common.Role] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.title","title":"title: str pydantic-field required","text":"

                                                                            A name given to the document, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.version","title":"version: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Metadata.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods","title":" Methods (Enum) ","text":"

                                                                            Identifies how the observation was made.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Methods(Enum):\n\"\"\"\n    Identifies how the observation was made.\n    \"\"\"\n\n    EXAMINE = 'EXAMINE'\n    INTERVIEW = 'INTERVIEW'\n    TEST = 'TEST'\n    UNKNOWN = 'UNKNOWN'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.EXAMINE","title":"EXAMINE","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.INTERVIEW","title":"INTERVIEW","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.TEST","title":"TEST","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Methods.UNKNOWN","title":"UNKNOWN","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor","title":" MitigatingFactor (OscalBaseModel) pydantic-model","text":"

                                                                            Describes an existing mitigating factor that may affect the overall determination of the risk, with an optional link to an implementation statement in the SSP.

                                                                            Source code in trestle/oscal/common.py
                                                                            class MitigatingFactor(OscalBaseModel):\n\"\"\"\n    Describes an existing mitigating factor that may affect the overall determination of the risk, with an optional link to an implementation statement in the SSP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this mitigating factor elsewhere in this or other OSCAL instances. The locally defined UUID of the mitigating factor can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Mitigating Factor Universally Unique Identifier',\n    )\n    implementation_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='implementation-uuid',\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this implementation statement elsewhere in this or other OSCAL instancess. The locally defined UUID of the implementation statement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Implementation UUID',\n    )\n    description: str = Field(\n        ...,\n        description='A human-readable description of this mitigating factor.',\n        title='Mitigating Factor Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    subjects: Optional[List[SubjectReference]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this mitigating factor.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.implementation_uuid","title":"implementation_uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this implementation statement elsewhere in this or other OSCAL instancess. The locally defined UUID of the implementation statement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.subjects","title":"subjects: List[trestle.oscal.common.SubjectReference] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this mitigating factor elsewhere in this or other OSCAL instances. The locally defined UUID of the mitigating factor can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.MitigatingFactor.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name","title":" Name (Enum) ","text":"

                                                                            A textual label that uniquely identifies the part's semantic type.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Name(Enum):\n\"\"\"\n    A textual label that uniquely identifies the part's semantic type.\n    \"\"\"\n\n    asset = 'asset'\n    method = 'method'\n    objective = 'objective'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name.asset","title":"asset","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name.method","title":"method","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Name.objective","title":"objective","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues","title":" NamingSystemValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class NamingSystemValidValues(Enum):\n    http___fedramp_gov = 'http://fedramp.gov'\n    http___fedramp_gov_ns_oscal = 'http://fedramp.gov/ns/oscal'\n    http___csrc_nist_gov_ns_oscal = 'http://csrc.nist.gov/ns/oscal'\n    http___csrc_nist_gov_ns_oscal_unknown = 'http://csrc.nist.gov/ns/oscal/unknown'\n    http___cve_mitre_org = 'http://cve.mitre.org'\n    http___www_first_org_cvss_v2_0 = 'http://www.first.org/cvss/v2.0'\n    http___www_first_org_cvss_v3_0 = 'http://www.first.org/cvss/v3.0'\n    http___www_first_org_cvss_v3_1 = 'http://www.first.org/cvss/v3.1'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___csrc_nist_gov_ns_oscal","title":"http___csrc_nist_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___csrc_nist_gov_ns_oscal_unknown","title":"http___csrc_nist_gov_ns_oscal_unknown","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___cve_mitre_org","title":"http___cve_mitre_org","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___fedramp_gov","title":"http___fedramp_gov","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___fedramp_gov_ns_oscal","title":"http___fedramp_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___www_first_org_cvss_v2_0","title":"http___www_first_org_cvss_v2_0","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___www_first_org_cvss_v3_0","title":"http___www_first_org_cvss_v3_0","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NamingSystemValidValues.http___www_first_org_cvss_v3_1","title":"http___www_first_org_cvss_v3_1","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype","title":" NonNegativeIntegerDatatype (OscalBaseModel) pydantic-model","text":"

                                                                            An integer value that is equal to or greater than 0.

                                                                            Source code in trestle/oscal/common.py
                                                                            class NonNegativeIntegerDatatype(OscalBaseModel):\n\"\"\"\n    An integer value that is equal to or greater than 0.\n    \"\"\"\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.NonNegativeIntegerDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus","title":" ObjectiveStatus (OscalBaseModel) pydantic-model","text":"

                                                                            A determination of if the objective is satisfied or not within a given system.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ObjectiveStatus(OscalBaseModel):\n\"\"\"\n    A determination of if the objective is satisfied or not within a given system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: ObjectiveStatusStateValidValues = Field(\n        ...,\n        description='An indication as to whether the objective is satisfied or not.',\n        title='Objective Status State'\n    )\n    reason: Optional[Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                           Reason]] = Field(\n                               None,\n                               description=\"The reason the objective was given it's status.\",\n                               title='Objective Status Reason'\n                           )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.reason","title":"reason: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Reason] pydantic-field","text":"

                                                                            The reason the objective was given it's status.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.state","title":"state: ObjectiveStatusStateValidValues pydantic-field required","text":"

                                                                            An indication as to whether the objective is satisfied or not.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatus.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatusStateValidValues","title":" ObjectiveStatusStateValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class ObjectiveStatusStateValidValues(Enum):\n    satisfied = 'satisfied'\n    not_satisfied = 'not-satisfied'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatusStateValidValues.not_satisfied","title":"not_satisfied","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObjectiveStatusStateValidValues.satisfied","title":"satisfied","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation","title":" Observation (OscalBaseModel) pydantic-model","text":"

                                                                            Describes an individual observation.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Observation(OscalBaseModel):\n\"\"\"\n    Describes an individual observation.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this observation elsewhere in this or other OSCAL instances. The locally defined UUID of the observation can be used to reference the data item locally or globally (e.g., in an imorted OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Observation Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this observation.', title='Observation Title')\n    description: str = Field(\n        ...,\n        description='A human-readable description of this assessment observation.',\n        title='Observation Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    methods: List[Union[constr(regex=r'^\\S(.*\\S)?$'), Methods]] = Field(...)\n    types: Optional[List[Union[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ),\n                               ObservationTypeValidValues]]] = Field(None)\n    origins: Optional[List[Origin]] = Field(None)\n    subjects: Optional[List[SubjectReference]] = Field(None)\n    relevant_evidence: Optional[List[RelevantEvidence]] = Field(None, alias='relevant-evidence')\n    collected: datetime = Field(\n        ...,\n        description='Date/time stamp identifying when the finding information was collected.',\n        title='Collected Field'\n    )\n    expires: Optional[datetime] = Field(\n        None,\n        description=\n        'Date/time identifying when the finding information is out-of-date and no longer valid. Typically used with continuous assessment scenarios.',\n        title='Expires Field'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.collected","title":"collected: datetime pydantic-field required","text":"

                                                                            Date/time stamp identifying when the finding information was collected.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this assessment observation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.expires","title":"expires: datetime pydantic-field","text":"

                                                                            Date/time identifying when the finding information is out-of-date and no longer valid. Typically used with continuous assessment scenarios.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.methods","title":"methods: List[Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Methods]] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.relevant_evidence","title":"relevant_evidence: List[trestle.oscal.common.RelevantEvidence] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.subjects","title":"subjects: List[trestle.oscal.common.SubjectReference] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.title","title":"title: str pydantic-field","text":"

                                                                            The title for this observation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.types","title":"types: List[Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.ObservationTypeValidValues]] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this observation elsewhere in this or other OSCAL instances. The locally defined UUID of the observation can be used to reference the data item locally or globally (e.g., in an imorted OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Observation.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues","title":" ObservationTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class ObservationTypeValidValues(Enum):\n    ssp_statement_issue = 'ssp-statement-issue'\n    control_objective = 'control-objective'\n    mitigation = 'mitigation'\n    finding = 'finding'\n    historic = 'historic'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.control_objective","title":"control_objective","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.finding","title":"finding","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.historic","title":"historic","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.mitigation","title":"mitigation","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ObservationTypeValidValues.ssp_statement_issue","title":"ssp_statement_issue","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate","title":" OnDate (OscalBaseModel) pydantic-model","text":"

                                                                            The task is intended to occur on the specified date.

                                                                            Source code in trestle/oscal/common.py
                                                                            class OnDate(OscalBaseModel):\n\"\"\"\n    The task is intended to occur on the specified date.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    date: datetime = Field(..., description='The task must occur on the specified date.', title='On Date Condition')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.date","title":"date: datetime pydantic-field required","text":"

                                                                            The task must occur on the specified date.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OnDate.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin","title":" Origin (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the source of the finding, such as a tool, interviewed person, or activity.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Origin(OscalBaseModel):\n\"\"\"\n    Identifies the source of the finding, such as a tool, interviewed person, or activity.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    actors: List[OriginActor] = Field(...)\n    related_tasks: Optional[List[RelatedTask]] = Field(None, alias='related-tasks')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.actors","title":"actors: List[trestle.oscal.common.OriginActor] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.related_tasks","title":"related_tasks: List[trestle.oscal.common.RelatedTask] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Origin.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor","title":" OriginActor (OscalBaseModel) pydantic-model","text":"

                                                                            The actor that produces an observation, a finding, or a risk. One or more actor type can be used to specify a person that is using a tool.

                                                                            Source code in trestle/oscal/common.py
                                                                            class OriginActor(OscalBaseModel):\n\"\"\"\n    The actor that produces an observation, a finding, or a risk. One or more actor type can be used to specify a person that is using a tool.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: OriginActorValidValues = Field(..., description='The kind of actor.', title='Actor Type')\n    actor_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='actor-uuid',\n        description='A machine-oriented identifier reference to the tool or person based on the associated type.',\n        title='Actor Universally Unique Identifier Reference'\n    )\n    role_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='role-id',\n        description='For a party, this can optionally be used to specify the role the actor was performing.',\n        title='Actor Role'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.actor_uuid","title":"actor_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to the tool or person based on the associated type.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.role_id","title":"role_id: ConstrainedStrValue pydantic-field","text":"

                                                                            For a party, this can optionally be used to specify the role the actor was performing.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.type","title":"type: OriginActorValidValues pydantic-field required","text":"

                                                                            The kind of actor.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActor.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues","title":" OriginActorValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class OriginActorValidValues(Enum):\n    tool = 'tool'\n    assessment_platform = 'assessment-platform'\n    party = 'party'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues.assessment_platform","title":"assessment_platform","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OriginActorValidValues.tool","title":"tool","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion","title":" OscalVersion (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class OscalVersion(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description='The OSCAL model version the document was authored against and will conform to as valid.',\n        title='OSCAL Version'\n    )\n\n    @validator('__root__')\n    def oscal_version_is_valid(cls, v):\n        strict_version = False\n        if not strict_version:\n            return v\n        p = re.compile(OSCAL_VERSION_REGEX)\n        matched = p.match(v)\n        if matched is None:\n            raise ValueError(f'OSCAL version: {v} is not supported, use {OSCAL_VERSION} instead.')\n        return v\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            The OSCAL model version the document was authored against and will conform to as valid.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.OscalVersion.oscal_version_is_valid","title":"oscal_version_is_valid(v) classmethod","text":"Source code in trestle/oscal/common.py
                                                                            @validator('__root__')\ndef oscal_version_is_valid(cls, v):\n    strict_version = False\n    if not strict_version:\n        return v\n    p = re.compile(OSCAL_VERSION_REGEX)\n    matched = p.match(v)\n    if matched is None:\n        raise ValueError(f'OSCAL version: {v} is not supported, use {OSCAL_VERSION} instead.')\n    return v\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter","title":" Parameter (OscalBaseModel) pydantic-model","text":"

                                                                            Parameters provide a mechanism for the dynamic assignment of value(s) in a control.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Parameter(OscalBaseModel):\n\"\"\"\n    Parameters provide a mechanism for the dynamic assignment of value(s) in a control.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., description='A unique identifier for the parameter.', title='Parameter Identifier')\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\n        'A textual label that provides a characterization of the type, purpose, use or scope of the parameter.',\n        title='Parameter Class'\n    )\n    depends_on: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='depends-on',\n        description=\n        '(deprecated) Another parameter invoking this one. This construct has been deprecated and should not be used.',\n        title='Depends on'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    label: Optional[str] = Field(\n        None,\n        description=\n        'A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.',\n        title='Parameter Label'\n    )\n    usage: Optional[str] = Field(\n        None, description='Describes the purpose and use of a parameter.', title='Parameter Usage Description'\n    )\n    constraints: Optional[List[ParameterConstraint]] = Field(None)\n    guidelines: Optional[List[ParameterGuideline]] = Field(None)\n    values: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None)\n    select: Optional[ParameterSelection] = None\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            A textual label that provides a characterization of the type, purpose, use or scope of the parameter.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.constraints","title":"constraints: List[trestle.oscal.common.ParameterConstraint] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.depends_on","title":"depends_on: ConstrainedStrValue pydantic-field","text":"

                                                                            (deprecated) Another parameter invoking this one. This construct has been deprecated and should not be used.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.guidelines","title":"guidelines: List[trestle.oscal.common.ParameterGuideline] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.id","title":"id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A unique identifier for the parameter.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.label","title":"label: str pydantic-field","text":"

                                                                            A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.select","title":"select: ParameterSelection pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.usage","title":"usage: str pydantic-field","text":"

                                                                            Describes the purpose and use of a parameter.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Parameter.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint","title":" ParameterConstraint (OscalBaseModel) pydantic-model","text":"

                                                                            A formal or informal expression of a constraint or test.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ParameterConstraint(OscalBaseModel):\n\"\"\"\n    A formal or informal expression of a constraint or test.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None, description='A textual summary of the constraint to be applied.', title='Constraint Description'\n    )\n    tests: Optional[List[Test]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.description","title":"description: str pydantic-field","text":"

                                                                            A textual summary of the constraint to be applied.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.tests","title":"tests: List[trestle.oscal.common.Test] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterConstraint.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline","title":" ParameterGuideline (OscalBaseModel) pydantic-model","text":"

                                                                            A prose statement that provides a recommendation for the use of a parameter.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ParameterGuideline(OscalBaseModel):\n\"\"\"\n    A prose statement that provides a recommendation for the use of a parameter.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    prose: str = Field(..., description='Prose permits multiple paragraphs, lists, tables etc.', title='Guideline Text')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.prose","title":"prose: str pydantic-field required","text":"

                                                                            Prose permits multiple paragraphs, lists, tables etc.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterGuideline.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection","title":" ParameterSelection (OscalBaseModel) pydantic-model","text":"

                                                                            Presenting a choice among alternatives.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ParameterSelection(OscalBaseModel):\n\"\"\"\n    Presenting a choice among alternatives.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    how_many: Optional[HowManyValidValues] = Field(\n        None,\n        alias='how-many',\n        description=\n        'Describes the number of selections that must occur. Without this setting, only one value should be assumed to be permitted.',\n        title='Parameter Cardinality'\n    )\n    choice: Optional[List[str]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.choice","title":"choice: List[str] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.how_many","title":"how_many: HowManyValidValues pydantic-field","text":"

                                                                            Describes the number of selections that must occur. Without this setting, only one value should be assumed to be permitted.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterSelection.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue","title":" ParameterValue (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class ParameterValue(OscalBaseModel):\n    __root__: StringDatatype = Field(..., description='A parameter value or set of values.', title='Parameter Value')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                                                            A parameter value or set of values.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ParameterValue.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part","title":" Part (OscalBaseModel) pydantic-model","text":"

                                                                            An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Part(OscalBaseModel):\n\"\"\"\n    An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, description='A unique identifier for the part.', title='Part Identifier'\n    )\n    name: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        \"A textual label that uniquely identifies the part's semantic type, which exists in a value space qualified by the ns.\",\n        title='Part Name'\n    )\n    ns: Optional[AnyUrl] = Field(\n        None,\n        description=\n        \"An optional namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.\",\n        title='Part Namespace'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\n        \"An optional textual providing a sub-type or characterization of the part's name, or a category to which the part belongs.\",\n        title='Part Class'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='An optional name given to the part, which may be used by a tool for display and navigation.',\n        title='Part Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    prose: Optional[str] = Field(None, description='Permits multiple paragraphs, lists, tables etc.', title='Part Text')\n    parts: Optional[List[Part]] = None\n    links: Optional[List[Link]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            An optional textual providing a sub-type or characterization of the part's name, or a category to which the part belongs.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.id","title":"id: ConstrainedStrValue pydantic-field","text":"

                                                                            A unique identifier for the part.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                                                            A textual label that uniquely identifies the part's semantic type, which exists in a value space qualified by the ns.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.ns","title":"ns: AnyUrl pydantic-field","text":"

                                                                            An optional namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.prose","title":"prose: str pydantic-field","text":"

                                                                            Permits multiple paragraphs, lists, tables etc.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.title","title":"title: str pydantic-field","text":"

                                                                            An optional name given to the part, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Part.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party","title":" Party (OscalBaseModel) pydantic-model","text":"

                                                                            An organization or person, which may be associated with roles or other concepts within the current or linked OSCAL document.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Party(OscalBaseModel):\n\"\"\"\n    An organization or person, which may be associated with roles or other concepts within the current or linked OSCAL document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(..., description='A unique identifier for the party.', title='Party Universally Unique Identifier')\n    type: PartyTypeValidValues = Field(\n        ..., description='A category describing the kind of party the object describes.', title='Party Type'\n    )\n    name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        description='The full name of the party. This is typically the legal name associated with the party.',\n        title='Party Name'\n    )\n    short_name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='short-name',\n        description='A short common name, abbreviation, or acronym for the party.',\n        title='Party Short Name'\n    )\n    external_ids: Optional[List[ExternalId]] = Field(None, alias='external-ids')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    email_addresses: Optional[List[EmailAddress]] = Field(None, alias='email-addresses')\n    telephone_numbers: Optional[List[TelephoneNumber]] = Field(None, alias='telephone-numbers')\n    addresses: Optional[List[Address]] = Field(None)\n    location_uuids: Optional[List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )]] = Field(\n        None, alias='location-uuids'\n    )\n    member_of_organizations: Optional[List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )]] = Field(\n        None, alias='member-of-organizations'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.addresses","title":"addresses: List[trestle.oscal.common.Address] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.email_addresses","title":"email_addresses: List[trestle.oscal.common.EmailAddress] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.external_ids","title":"external_ids: List[trestle.oscal.common.ExternalId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.location_uuids","title":"location_uuids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.member_of_organizations","title":"member_of_organizations: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.name","title":"name: ConstrainedStrValue pydantic-field","text":"

                                                                            The full name of the party. This is typically the legal name associated with the party.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.short_name","title":"short_name: ConstrainedStrValue pydantic-field","text":"

                                                                            A short common name, abbreviation, or acronym for the party.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.telephone_numbers","title":"telephone_numbers: List[trestle.oscal.common.TelephoneNumber] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.type","title":"type: PartyTypeValidValues pydantic-field required","text":"

                                                                            A category describing the kind of party the object describes.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A unique identifier for the party.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Party.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyTypeValidValues","title":" PartyTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class PartyTypeValidValues(Enum):\n    person = 'person'\n    organization = 'organization'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyTypeValidValues.organization","title":"organization","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyTypeValidValues.person","title":"person","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid","title":" PartyUuid (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class PartyUuid(OscalBaseModel):\n    __root__: UUIDDatatype = Field(\n        ..., description='Reference to a party by UUID.', title='Party Universally Unique Identifier Reference'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__root__","title":"__root__: UUIDDatatype pydantic-field required special","text":"

                                                                            Reference to a party by UUID.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PartyUuid.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange","title":" PortRange (OscalBaseModel) pydantic-model","text":"

                                                                            Where applicable this is the IPv4 port range on which the service operates.

                                                                            Source code in trestle/oscal/common.py
                                                                            class PortRange(OscalBaseModel):\n\"\"\"\n    Where applicable this is the IPv4 port range on which the service operates.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    start: Optional[conint(ge=0, multiple_of=1)] = Field(\n        None, description='Indicates the starting port number in a port range', title='Start'\n    )\n    end: Optional[conint(ge=0, multiple_of=1)] = Field(\n        None, description='Indicates the ending port number in a port range', title='End'\n    )\n    transport: Optional[PortRangeValidValues] = Field(\n        None, description='Indicates the transport type.', title='Transport'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.end","title":"end: ConstrainedIntValue pydantic-field","text":"

                                                                            Indicates the ending port number in a port range

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.start","title":"start: ConstrainedIntValue pydantic-field","text":"

                                                                            Indicates the starting port number in a port range

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.transport","title":"transport: PortRangeValidValues pydantic-field","text":"

                                                                            Indicates the transport type.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRange.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRangeValidValues","title":" PortRangeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class PortRangeValidValues(Enum):\n    TCP = 'TCP'\n    UDP = 'UDP'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRangeValidValues.TCP","title":"TCP","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PortRangeValidValues.UDP","title":"UDP","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype","title":" PositiveIntegerDatatype (OscalBaseModel) pydantic-model","text":"

                                                                            An integer value that is greater than 0.

                                                                            Source code in trestle/oscal/common.py
                                                                            class PositiveIntegerDatatype(OscalBaseModel):\n\"\"\"\n    An integer value that is greater than 0.\n    \"\"\"\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.PositiveIntegerDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property","title":" Property (OscalBaseModel) pydantic-model","text":"

                                                                            An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Property(OscalBaseModel):\n\"\"\"\n    An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    name: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        \"A textual label, within a namespace, that uniquely identifies a specific attribute, characteristic, or quality of the property's containing object.\",\n        title='Property Name'\n    )\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None, description='A unique identifier for a property.', title='Property Universally Unique Identifier'\n    )\n    ns: Optional[AnyUrl] = Field(\n        None,\n        description=\n        \"A namespace qualifying the property's name. This allows different organizations to associate distinct semantics with the same name.\",\n        title='Property Namespace'\n    )\n    value: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ..., description='Indicates the value of the attribute, characteristic, or quality.', title='Property Value'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description=\"A textual label that provides a sub-type or characterization of the property's name.\",\n        title='Property Class'\n    )\n    group: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, description='An identifier for relating distinct sets of properties.', title='Property Group'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            A textual label that provides a sub-type or characterization of the property's name.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.group","title":"group: ConstrainedStrValue pydantic-field","text":"

                                                                            An identifier for relating distinct sets of properties.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                                                            A textual label, within a namespace, that uniquely identifies a specific attribute, characteristic, or quality of the property's containing object.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.ns","title":"ns: AnyUrl pydantic-field","text":"

                                                                            A namespace qualifying the property's name. This allows different organizations to associate distinct semantics with the same name.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A unique identifier for a property.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.value","title":"value: ConstrainedStrValue pydantic-field required","text":"

                                                                            Indicates the value of the attribute, characteristic, or quality.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Property.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol","title":" Protocol (OscalBaseModel) pydantic-model","text":"

                                                                            Information about the protocol used to provide a service.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Protocol(OscalBaseModel):\n\"\"\"\n    Information about the protocol used to provide a service.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this service protocol information elsewhere in this or other OSCAL instances. The locally defined UUID of the service protocol can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Service Protocol Information Universally Unique Identifier',\n    )\n    name: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description=\n        'The common name of the protocol, which should be the appropriate \"service name\" from the IANA Service Name and Transport Protocol Port Number Registry.',\n        title='Protocol Name'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A human readable name for the protocol (e.g., Transport Layer Security).',\n        title='Protocol Title'\n    )\n    port_ranges: Optional[List[PortRange]] = Field(None, alias='port-ranges')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                                                            The common name of the protocol, which should be the appropriate \"service name\" from the IANA Service Name and Transport Protocol Port Number Registry.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.port_ranges","title":"port_ranges: List[trestle.oscal.common.PortRange] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.title","title":"title: str pydantic-field","text":"

                                                                            A human readable name for the protocol (e.g., Transport Layer Security).

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this service protocol information elsewhere in this or other OSCAL instances. The locally defined UUID of the service protocol can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Protocol.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published","title":" Published (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class Published(OscalBaseModel):\n    __root__: DateTimeWithTimezoneDatatype = Field(\n        ..., description='The date and time the document was last made available.', title='Publication Timestamp'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__root__","title":"__root__: DateTimeWithTimezoneDatatype pydantic-field required special","text":"

                                                                            The date and time the document was last made available.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Published.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason","title":" Reason (Enum) ","text":"

                                                                            The reason the objective was given it's status.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Reason(Enum):\n\"\"\"\n    The reason the objective was given it's status.\n    \"\"\"\n\n    pass_ = 'pass'\n    fail = 'fail'\n    other = 'other'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason.fail","title":"fail","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason.other","title":"other","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Reason.pass_","title":"pass_","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rel","title":" Rel (Enum) ","text":"

                                                                            Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Rel(Enum):\n\"\"\"\n    Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.\n    \"\"\"\n\n    reference = 'reference'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rel.reference","title":"reference","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation","title":" RelatedObservation (OscalBaseModel) pydantic-model","text":"

                                                                            Relates the finding to a set of referenced observations that were used to determine the finding.

                                                                            Source code in trestle/oscal/common.py
                                                                            class RelatedObservation(OscalBaseModel):\n\"\"\"\n    Relates the finding to a set of referenced observations that were used to determine the finding.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    observation_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='observation-uuid',\n        description='A machine-oriented identifier reference to an observation defined in the list of observations.',\n        title='Observation Universally Unique Identifier Reference'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.observation_uuid","title":"observation_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to an observation defined in the list of observations.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedObservation.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse","title":" RelatedResponse (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies an individual risk response that this log entry is for.

                                                                            Source code in trestle/oscal/common.py
                                                                            class RelatedResponse(OscalBaseModel):\n\"\"\"\n    Identifies an individual risk response that this log entry is for.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    response_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='response-uuid',\n        description='A machine-oriented identifier reference to a unique risk response.',\n        title='Response Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    related_tasks: Optional[List[RelatedTask]] = Field(None, alias='related-tasks')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.related_tasks","title":"related_tasks: List[trestle.oscal.common.RelatedTask] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.response_uuid","title":"response_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a unique risk response.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedResponse.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk","title":" RelatedRisk (OscalBaseModel) pydantic-model","text":"

                                                                            Relates the finding to a set of referenced risks that were used to determine the finding.

                                                                            Source code in trestle/oscal/common.py
                                                                            class RelatedRisk(OscalBaseModel):\n\"\"\"\n    Relates the finding to a set of referenced risks that were used to determine the finding.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    risk_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='risk-uuid',\n        description='A machine-oriented identifier reference to a risk defined in the list of risks.',\n        title='Risk Universally Unique Identifier Reference'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.risk_uuid","title":"risk_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a risk defined in the list of risks.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedRisk.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask","title":" RelatedTask (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies an individual task for which the containing object is a consequence of.

                                                                            Source code in trestle/oscal/common.py
                                                                            class RelatedTask(OscalBaseModel):\n\"\"\"\n    Identifies an individual task for which the containing object is a consequence of.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    task_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='task-uuid',\n        description='A machine-oriented identifier reference to a unique task.',\n        title='Task Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    subjects: Optional[List[AssessmentSubject]] = Field(None)\n    identified_subject: Optional[IdentifiedSubject] = Field(\n        None,\n        alias='identified-subject',\n        description='Used to detail assessment subjects that were identfied by this task.',\n        title='Identified Subject'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.identified_subject","title":"identified_subject: IdentifiedSubject pydantic-field","text":"

                                                                            Used to detail assessment subjects that were identfied by this task.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.task_uuid","title":"task_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a unique task.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelatedTask.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence","title":" RelevantEvidence (OscalBaseModel) pydantic-model","text":"

                                                                            Links this observation to relevant evidence.

                                                                            Source code in trestle/oscal/common.py
                                                                            class RelevantEvidence(OscalBaseModel):\n\"\"\"\n    Links this observation to relevant evidence.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: Optional[str] = Field(\n        None, description='A resolvable URL reference to relevant evidence.', title='Relevant Evidence Reference'\n    )\n    description: str = Field(\n        ..., description='A human-readable description of this evidence.', title='Relevant Evidence Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this evidence.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.href","title":"href: str pydantic-field","text":"

                                                                            A resolvable URL reference to relevant evidence.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RelevantEvidence.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks","title":" Remarks (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class Remarks(OscalBaseModel):\n    __root__: str = Field(..., description='Additional commentary about the containing object.', title='Remarks')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__root__","title":"__root__: str pydantic-field required special","text":"

                                                                            Additional commentary about the containing object.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Remarks.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset","title":" RequiredAsset (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies an asset required to achieve remediation.

                                                                            Source code in trestle/oscal/common.py
                                                                            class RequiredAsset(OscalBaseModel):\n\"\"\"\n    Identifies an asset required to achieve remediation.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this required asset elsewhere in this or other OSCAL instances. The locally defined UUID of the asset can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Required Universally Unique Identifier',\n    )\n    subjects: Optional[List[SubjectReference]] = Field(None)\n    title: Optional[str] = Field(\n        None, description='The title for this required asset.', title='Title for Required Asset'\n    )\n    description: str = Field(\n        ..., description='A human-readable description of this required asset.', title='Description of Required Asset'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this required asset.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.subjects","title":"subjects: List[trestle.oscal.common.SubjectReference] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.title","title":"title: str pydantic-field","text":"

                                                                            The title for this required asset.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this required asset elsewhere in this or other OSCAL instances. The locally defined UUID of the asset can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RequiredAsset.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource","title":" Resource (OscalBaseModel) pydantic-model","text":"

                                                                            A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Resource(OscalBaseModel):\n\"\"\"\n    A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(..., description='A unique identifier for a resource.', title='Resource Universally Unique Identifier')\n    title: Optional[str] = Field(\n        None,\n        description='An optional name given to the resource, which may be used by a tool for display and navigation.',\n        title='Resource Title'\n    )\n    description: Optional[str] = Field(\n        None,\n        description='An optional short summary of the resource used to indicate the purpose of the resource.',\n        title='Resource Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    document_ids: Optional[List[DocumentId]] = Field(None, alias='document-ids')\n    citation: Optional[Citation] = Field(\n        None, description='An optional citation consisting of end note text using structured markup.', title='Citation'\n    )\n    rlinks: Optional[List[Rlink]] = Field(None)\n    base64: Optional[Base64] = Field(\n        None, description='A resource encoded using the Base64 alphabet defined by RFC 2045.', title='Base64'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.base64","title":"base64: Base64 pydantic-field","text":"

                                                                            A resource encoded using the Base64 alphabet defined by RFC 2045.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.citation","title":"citation: Citation pydantic-field","text":"

                                                                            An optional citation consisting of end note text using structured markup.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.description","title":"description: str pydantic-field","text":"

                                                                            An optional short summary of the resource used to indicate the purpose of the resource.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.document_ids","title":"document_ids: List[trestle.oscal.common.DocumentId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.rlinks","title":"rlinks: List[trestle.oscal.common.Rlink] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.title","title":"title: str pydantic-field","text":"

                                                                            An optional name given to the resource, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A unique identifier for a resource.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Resource.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response","title":" Response (OscalBaseModel) pydantic-model","text":"

                                                                            Describes either recommended or an actual plan for addressing the risk.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Response(OscalBaseModel):\n\"\"\"\n    Describes either recommended or an actual plan for addressing the risk.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this remediation elsewhere in this or other OSCAL instances. The locally defined UUID of the risk response can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Remediation Universally Unique Identifier',\n    )\n    lifecycle: Union[\n        constr(\n            regex=\n            r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n        ),\n        Lifecycle\n    ] = Field(\n        ...,\n        description=\n        'Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.',\n        title='Remediation Intent'\n    )\n    title: str = Field(..., description='The title for this response activity.', title='Response Title')\n    description: str = Field(\n        ..., description='A human-readable description of this response plan.', title='Response Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    origins: Optional[List[Origin]] = Field(None)\n    required_assets: Optional[List[RequiredAsset]] = Field(None, alias='required-assets')\n    tasks: Optional[List[Task]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this response plan.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.lifecycle","title":"lifecycle: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.Lifecycle] pydantic-field required","text":"

                                                                            Identifies whether this is a recommendation, such as from an assessor or tool, or an actual plan accepted by the system owner.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.required_assets","title":"required_assets: List[trestle.oscal.common.RequiredAsset] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.title","title":"title: str pydantic-field required","text":"

                                                                            The title for this response activity.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this remediation elsewhere in this or other OSCAL instances. The locally defined UUID of the risk response can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Response.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty","title":" ResponsibleParty (OscalBaseModel) pydantic-model","text":"

                                                                            A reference to a set of persons and/or organizations that have responsibility for performing the referenced role in the context of the containing object.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ResponsibleParty(OscalBaseModel):\n\"\"\"\n    A reference to a set of persons and/or organizations that have responsibility for performing the referenced role in the context of the containing object.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    role_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ..., alias='role-id', description='A reference to a role performed by a party.', title='Responsible Role'\n    )\n    party_uuids: List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(..., alias='party-uuids')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.party_uuids","title":"party_uuids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.role_id","title":"role_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A reference to a role performed by a party.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleParty.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole","title":" ResponsibleRole (OscalBaseModel) pydantic-model","text":"

                                                                            A reference to a role with responsibility for performing a function relative to the containing object, optionally associated with a set of persons and/or organizations that perform that role.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ResponsibleRole(OscalBaseModel):\n\"\"\"\n    A reference to a role with responsibility for performing a function relative to the containing object, optionally associated with a set of persons and/or organizations that perform that role.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    role_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='role-id',\n        description='A human-oriented identifier reference to a role performed.',\n        title='Responsible Role ID'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    party_uuids: Optional[List[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )]] = Field(\n        None, alias='party-uuids'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.party_uuids","title":"party_uuids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.role_id","title":"role_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented identifier reference to a role performed.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ResponsibleRole.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls","title":" ReviewedControls (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the controls being assessed and their control objectives.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ReviewedControls(OscalBaseModel):\n\"\"\"\n    Identifies the controls being assessed and their control objectives.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None, description='A human-readable description of control objectives.', title='Control Objective Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    control_selections: List[ControlSelection] = Field(..., alias='control-selections')\n    control_objective_selections: Optional[List[ControlObjectiveSelection]] = Field(\n        None, alias='control-objective-selections'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.control_objective_selections","title":"control_objective_selections: List[trestle.oscal.common.ControlObjectiveSelection] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.control_selections","title":"control_selections: List[trestle.oscal.common.ControlSelection] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of control objectives.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ReviewedControls.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision","title":" Revision (OscalBaseModel) pydantic-model","text":"

                                                                            An entry in a sequential list of revisions to the containing document, expected to be in reverse chronological order (i.e. latest first).

                                                                            Source code in trestle/oscal/common.py
                                                                            class Revision(OscalBaseModel):\n\"\"\"\n    An entry in a sequential list of revisions to the containing document, expected to be in reverse chronological order (i.e. latest first).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the document revision, which may be used by a tool for display and navigation.',\n        title='Document Title'\n    )\n    published: Optional[datetime] = None\n    last_modified: Optional[datetime] = Field(None, alias='last-modified')\n    version: constr(regex=r'^\\S(.*\\S)?$')\n    oscal_version: Optional[OscalVersion] = Field(None, alias='oscal-version')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.last_modified","title":"last_modified: datetime pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.oscal_version","title":"oscal_version: OscalVersion pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.published","title":"published: datetime pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.title","title":"title: str pydantic-field","text":"

                                                                            A name given to the document revision, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.version","title":"version: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Revision.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk","title":" Risk (OscalBaseModel) pydantic-model","text":"

                                                                            An identified risk.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Risk(OscalBaseModel):\n\"\"\"\n    An identified risk.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk elsewhere in this or other OSCAL instances. The locally defined UUID of the risk can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Risk Universally Unique Identifier',\n    )\n    title: str = Field(..., description='The title for this risk.', title='Risk Title')\n    description: str = Field(\n        ...,\n        description=\n        'A human-readable summary of the identified risk, to include a statement of how the risk impacts the system.',\n        title='Risk Description'\n    )\n    statement: str = Field(\n        ..., description='An summary of impact for how the risk affects the system.', title='Risk Statement'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    status: RiskStatus\n    origins: Optional[List[Origin]] = Field(None)\n    threat_ids: Optional[List[ThreatId]] = Field(None, alias='threat-ids')\n    characterizations: Optional[List[Characterization]] = Field(None)\n    mitigating_factors: Optional[List[MitigatingFactor]] = Field(None, alias='mitigating-factors')\n    deadline: Optional[datetime] = Field(\n        None, description='The date/time by which the risk must be resolved.', title='Risk Resolution Deadline'\n    )\n    remediations: Optional[List[Response]] = Field(None)\n    risk_log: Optional[RiskLog] = Field(\n        None, alias='risk-log', description='A log of all risk-related tasks taken.', title='Risk Log'\n    )\n    related_observations: Optional[List[RelatedObservation]] = Field(None, alias='related-observations')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.characterizations","title":"characterizations: List[trestle.oscal.common.Characterization] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.deadline","title":"deadline: datetime pydantic-field","text":"

                                                                            The date/time by which the risk must be resolved.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable summary of the identified risk, to include a statement of how the risk impacts the system.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.mitigating_factors","title":"mitigating_factors: List[trestle.oscal.common.MitigatingFactor] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.origins","title":"origins: List[trestle.oscal.common.Origin] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.related_observations","title":"related_observations: List[trestle.oscal.common.RelatedObservation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.remediations","title":"remediations: List[trestle.oscal.common.Response] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.risk_log","title":"risk_log: RiskLog pydantic-field","text":"

                                                                            A log of all risk-related tasks taken.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.statement","title":"statement: str pydantic-field required","text":"

                                                                            An summary of impact for how the risk affects the system.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.status","title":"status: RiskStatus pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.threat_ids","title":"threat_ids: List[trestle.oscal.common.ThreatId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.title","title":"title: str pydantic-field required","text":"

                                                                            The title for this risk.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this risk elsewhere in this or other OSCAL instances. The locally defined UUID of the risk can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Risk.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog","title":" RiskLog (OscalBaseModel) pydantic-model","text":"

                                                                            A log of all risk-related tasks taken.

                                                                            Source code in trestle/oscal/common.py
                                                                            class RiskLog(OscalBaseModel):\n\"\"\"\n    A log of all risk-related tasks taken.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    entries: List[Entry] = Field(...)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.entries","title":"entries: List[trestle.oscal.common.Entry] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskLog.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus","title":" RiskStatus (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class RiskStatus(OscalBaseModel):\n    __root__: Union[TokenDatatype, RiskStatusValidValues] = Field(\n        ..., description='Describes the status of the associated risk.', title='Risk Status'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__root__","title":"__root__: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.RiskStatusValidValues] pydantic-field required special","text":"

                                                                            Describes the status of the associated risk.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatus.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues","title":" RiskStatusValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class RiskStatusValidValues(Enum):\n    open = 'open'\n    investigating = 'investigating'\n    remediating = 'remediating'\n    deviation_requested = 'deviation-requested'\n    deviation_approved = 'deviation-approved'\n    closed = 'closed'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.closed","title":"closed","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.deviation_approved","title":"deviation_approved","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.deviation_requested","title":"deviation_requested","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.investigating","title":"investigating","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.open","title":"open","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RiskStatusValidValues.remediating","title":"remediating","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink","title":" Rlink (OscalBaseModel) pydantic-model","text":"

                                                                            A URL-based pointer to an external resource with an optional hash for verification and change detection.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Rlink(OscalBaseModel):\n\"\"\"\n    A URL-based pointer to an external resource with an optional hash for verification and change detection.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ..., description='A resolvable URL pointing to the referenced resource.', title='Hypertext Reference'\n    )\n    media_type: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='media-type',\n        description='A label that indicates the nature of a resource, as a data serialization or format.',\n        title='Media Type'\n    )\n    hashes: Optional[List[Hash]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.hashes","title":"hashes: List[trestle.oscal.common.Hash] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.href","title":"href: str pydantic-field required","text":"

                                                                            A resolvable URL pointing to the referenced resource.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.media_type","title":"media_type: ConstrainedStrValue pydantic-field","text":"

                                                                            A label that indicates the nature of a resource, as a data serialization or format.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Rlink.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role","title":" Role (OscalBaseModel) pydantic-model","text":"

                                                                            Defines a function, which might be assigned to a party in a specific situation.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Role(OscalBaseModel):\n\"\"\"\n    Defines a function, which might be assigned to a party in a specific situation.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., description='A unique identifier for the role.', title='Role Identifier')\n    title: str = Field(\n        ...,\n        description='A name given to the role, which may be used by a tool for display and navigation.',\n        title='Role Title'\n    )\n    short_name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='short-name',\n        description='A short common name, abbreviation, or acronym for the role.',\n        title='Role Short Name'\n    )\n    description: Optional[str] = Field(\n        None, description=\"A summary of the role's purpose and associated responsibilities.\", title='Role Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.description","title":"description: str pydantic-field","text":"

                                                                            A summary of the role's purpose and associated responsibilities.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.id","title":"id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A unique identifier for the role.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.short_name","title":"short_name: ConstrainedStrValue pydantic-field","text":"

                                                                            A short common name, abbreviation, or acronym for the role.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.title","title":"title: str pydantic-field required","text":"

                                                                            A name given to the role, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Role.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId","title":" RoleId (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class RoleId(OscalBaseModel):\n    __root__: TokenDatatype = Field(..., description='Reference to a role by UUID.', title='Role Identifier Reference')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__root__","title":"__root__: TokenDatatype pydantic-field required special","text":"

                                                                            Reference to a role by UUID.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.RoleId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById","title":" SelectControlById (OscalBaseModel) pydantic-model","text":"

                                                                            Used to select a control for inclusion/exclusion based on one or more control identifiers. A set of statement identifiers can be used to target the inclusion/exclusion to only specific control statements providing more granularity over the specific statements that are within the asessment scope.

                                                                            Source code in trestle/oscal/common.py
                                                                            class SelectControlById(OscalBaseModel):\n\"\"\"\n    Used to select a control for inclusion/exclusion based on one or more control identifiers. A set of statement identifiers can be used to target the inclusion/exclusion to only specific control statements providing more granularity over the specific statements that are within the asessment scope.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    statement_ids: Optional[List[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )]] = Field(\n        None, alias='statement-ids'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.statement_ids","title":"statement_ids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectControlById.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById","title":" SelectObjectiveById (OscalBaseModel) pydantic-model","text":"

                                                                            Used to select a control objective for inclusion/exclusion based on the control objective's identifier.

                                                                            Source code in trestle/oscal/common.py
                                                                            class SelectObjectiveById(OscalBaseModel):\n\"\"\"\n    Used to select a control objective for inclusion/exclusion based on the control objective's identifier.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    objective_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., alias='objective-id', description='Points to an assessment objective.', title='Objective ID')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.objective_id","title":"objective_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            Points to an assessment objective.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectObjectiveById.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById","title":" SelectSubjectById (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies a set of assessment subjects to include/exclude by UUID.

                                                                            Source code in trestle/oscal/common.py
                                                                            class SelectSubjectById(OscalBaseModel):\n\"\"\"\n    Identifies a set of assessment subjects to include/exclude by UUID.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    subject_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='subject-uuid',\n        description=\n        \"A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.\",\n        title='Subject Universally Unique Identifier Reference'\n    )\n    type: Union[TokenDatatype, SelectSubjectByIdValidValues] = Field(\n        ...,\n        description='Used to indicate the type of object pointed to by the uuid-ref within a subject.',\n        title='Subject Universally Unique Identifier Reference Type'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.subject_uuid","title":"subject_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.SelectSubjectByIdValidValues] pydantic-field required","text":"

                                                                            Used to indicate the type of object pointed to by the uuid-ref within a subject.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectById.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues","title":" SelectSubjectByIdValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class SelectSubjectByIdValidValues(Enum):\n    component = 'component'\n    inventory_item = 'inventory-item'\n    location = 'location'\n    party = 'party'\n    user = 'user'\n    resource = 'resource'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.component","title":"component","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.inventory_item","title":"inventory_item","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.location","title":"location","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.resource","title":"resource","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SelectSubjectByIdValidValues.user","title":"user","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source","title":" Source (OscalBaseModel) pydantic-model","text":"

                                                                            Assessment subjects will be identified while conducting the referenced activity-instance.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Source(OscalBaseModel):\n\"\"\"\n    Assessment subjects will be identified while conducting the referenced activity-instance.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    task_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='task-uuid',\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference (in this or other OSCAL instances) an assessment activity to be performed as part of the event. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Task Universally Unique Identifier',\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.task_uuid","title":"task_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference (in this or other OSCAL instances) an assessment activity to be performed as part of the event. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Source.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State","title":" State (Enum) ","text":"

                                                                            Identifies the implementation status of the control or control objective.

                                                                            Source code in trestle/oscal/common.py
                                                                            class State(Enum):\n\"\"\"\n    Identifies the implementation status of the control or control objective.\n    \"\"\"\n\n    implemented = 'implemented'\n    partial = 'partial'\n    planned = 'planned'\n    alternative = 'alternative'\n    not_applicable = 'not-applicable'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.alternative","title":"alternative","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.implemented","title":"implemented","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.not_applicable","title":"not_applicable","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.partial","title":"partial","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.State.planned","title":"planned","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status","title":" Status (OscalBaseModel) pydantic-model","text":"

                                                                            Describes the operational status of the system component.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Status(OscalBaseModel):\n\"\"\"\n    Describes the operational status of the system component.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: SystemComponentOperationalStateValidValues = Field(..., description='The operational status.', title='State')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.state","title":"state: SystemComponentOperationalStateValidValues pydantic-field required","text":"

                                                                            The operational status.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Status.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step","title":" Step (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies an individual step in a series of steps related to an activity, such as an assessment test or examination procedure.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Step(OscalBaseModel):\n\"\"\"\n    Identifies an individual step in a series of steps related to an activity, such as an assessment test or examination procedure.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this step elsewhere in this or other OSCAL instances. The locally defined UUID of the step (in a series of steps) can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Step Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(None, description='The title for this step.', title='Step Title')\n    description: str = Field(..., description='A human-readable description of this step.', title='Step Description')\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    reviewed_controls: Optional[ReviewedControls] = Field(None, alias='reviewed-controls')\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of this step.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.reviewed_controls","title":"reviewed_controls: ReviewedControls pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.title","title":"title: str pydantic-field","text":"

                                                                            The title for this step.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this step elsewhere in this or other OSCAL instances. The locally defined UUID of the step (in a series of steps) can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Step.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype","title":" StringDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class StringDatatype(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description=\n        'A non-empty string with leading and trailing whitespace disallowed. Whitespace is: U+9, U+10, U+32 or [ \\n\\t]+'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            A non-empty string with leading and trailing whitespace disallowed. Whitespace is: U+9, U+10, U+32 or [ ]+

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.StringDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference","title":" SubjectReference (OscalBaseModel) pydantic-model","text":"

                                                                            A human-oriented identifier reference to a resource. Use type to indicate whether the identified resource is a component, inventory item, location, user, or something else.

                                                                            Source code in trestle/oscal/common.py
                                                                            class SubjectReference(OscalBaseModel):\n\"\"\"\n    A human-oriented identifier reference to a resource. Use type to indicate whether the identified resource is a component, inventory item, location, user, or something else.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    subject_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='subject-uuid',\n        description=\n        \"A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.\",\n        title='Subject Universally Unique Identifier Reference'\n    )\n    type: Union[TokenDatatype, SubjectReferenceValidValues] = Field(\n        ...,\n        description='Used to indicate the type of object pointed to by the uuid-ref within a subject.',\n        title='Subject Universally Unique Identifier Reference Type'\n    )\n    title: Optional[str] = Field(\n        None, description='The title or name for the referenced subject.', title='Subject Reference Title'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.subject_uuid","title":"subject_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a component, inventory-item, location, party, user, or resource using it's UUID.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.title","title":"title: str pydantic-field","text":"

                                                                            The title or name for the referenced subject.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.SubjectReferenceValidValues] pydantic-field required","text":"

                                                                            Used to indicate the type of object pointed to by the uuid-ref within a subject.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReference.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues","title":" SubjectReferenceValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class SubjectReferenceValidValues(Enum):\n    component = 'component'\n    inventory_item = 'inventory-item'\n    location = 'location'\n    party = 'party'\n    user = 'user'\n    resource = 'resource'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.component","title":"component","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.inventory_item","title":"inventory_item","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.location","title":"location","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.party","title":"party","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.resource","title":"resource","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SubjectReferenceValidValues.user","title":"user","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent","title":" SystemComponent (OscalBaseModel) pydantic-model","text":"

                                                                            A defined component that can be part of an implemented system.

                                                                            Source code in trestle/oscal/common.py
                                                                            class SystemComponent(OscalBaseModel):\n\"\"\"\n    A defined component that can be part of an implemented system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Component Identifier',\n    )\n    type: Union[constr(regex=r'^\\S(.*\\S)?$'), SystemComponentTypeValidValues] = Field(\n        ..., description='A category describing the purpose of the component.', title='Component Type'\n    )\n    title: str = Field(..., description='A human readable name for the system component.', title='Component Title')\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description'\n    )\n    purpose: Optional[str] = Field(\n        None, description='A summary of the technological or business purpose of the component.', title='Purpose'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    status: Status = Field(..., description='Describes the operational status of the system component.', title='Status')\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    protocols: Optional[List[Protocol]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.description","title":"description: str pydantic-field required","text":"

                                                                            A description of the component, including information about its function.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.protocols","title":"protocols: List[trestle.oscal.common.Protocol] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.purpose","title":"purpose: str pydantic-field","text":"

                                                                            A summary of the technological or business purpose of the component.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.status","title":"status: Status pydantic-field required","text":"

                                                                            Describes the operational status of the system component.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.title","title":"title: str pydantic-field required","text":"

                                                                            A human readable name for the system component.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.type","title":"type: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.common.SystemComponentTypeValidValues] pydantic-field required","text":"

                                                                            A category describing the purpose of the component.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this component elsewhere in this or other OSCAL instances. The locally defined UUID of the component can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponent.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues","title":" SystemComponentOperationalStateValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class SystemComponentOperationalStateValidValues(Enum):\n    under_development = 'under-development'\n    operational = 'operational'\n    disposition = 'disposition'\n    other = 'other'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.disposition","title":"disposition","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.operational","title":"operational","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.other","title":"other","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentOperationalStateValidValues.under_development","title":"under_development","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues","title":" SystemComponentTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class SystemComponentTypeValidValues(Enum):\n    this_system = 'this-system'\n    system = 'system'\n    interconnection = 'interconnection'\n    software = 'software'\n    hardware = 'hardware'\n    service = 'service'\n    policy = 'policy'\n    physical = 'physical'\n    process_procedure = 'process-procedure'\n    plan = 'plan'\n    guidance = 'guidance'\n    standard = 'standard'\n    validation = 'validation'\n    network = 'network'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.guidance","title":"guidance","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.hardware","title":"hardware","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.interconnection","title":"interconnection","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.network","title":"network","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.physical","title":"physical","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.plan","title":"plan","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.policy","title":"policy","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.process_procedure","title":"process_procedure","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.service","title":"service","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.software","title":"software","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.standard","title":"standard","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.system","title":"system","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.this_system","title":"this_system","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemComponentTypeValidValues.validation","title":"validation","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId","title":" SystemId (OscalBaseModel) pydantic-model","text":"

                                                                            A human-oriented, globally unique identifier with cross-instance scope that can be used to reference this system identification property elsewhere in this or other OSCAL instances. When referencing an externally defined system identification, the system identification must be used in the context of the external / imported OSCAL instance (e.g., uri-reference). This string should be assigned per-subject, which means it should be consistently used to identify the same system across revisions of the document.

                                                                            Source code in trestle/oscal/common.py
                                                                            class SystemId(OscalBaseModel):\n\"\"\"\n    A human-oriented, globally unique identifier with cross-instance scope that can be used to reference this system identification property elsewhere in this or other OSCAL instances. When referencing an externally defined system identification, the system identification must be used in the context of the external / imported OSCAL instance (e.g., uri-reference). This string should be assigned per-subject, which means it should be consistently used to identify the same system across revisions of the document.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    identifier_type: Optional[Union[AnyUrl, IdentifierType]] = Field(\n        None,\n        alias='identifier-type',\n        description='Identifies the identification system from which the provided identifier was assigned.',\n        title='Identification System Type'\n    )\n    id: constr(regex=r'^\\S(.*\\S)?$')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.id","title":"id: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.identifier_type","title":"identifier_type: Union[pydantic.v1.networks.AnyUrl, trestle.oscal.common.IdentifierType] pydantic-field","text":"

                                                                            Identifies the identification system from which the provided identifier was assigned.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser","title":" SystemUser (OscalBaseModel) pydantic-model","text":"

                                                                            A type of user that interacts with the system based on an associated role.

                                                                            Source code in trestle/oscal/common.py
                                                                            class SystemUser(OscalBaseModel):\n\"\"\"\n    A type of user that interacts with the system based on an associated role.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this user class elsewhere in this or other OSCAL instances. The locally defined UUID of the system user can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='User Universally Unique Identifier',\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the user, which may be used by a tool for display and navigation.',\n        title='User Title'\n    )\n    short_name: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='short-name',\n        description='A short common name, abbreviation, or acronym for the user.',\n        title='User Short Name'\n    )\n    description: Optional[str] = Field(\n        None, description=\"A summary of the user's purpose within the system.\", title='User Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    role_ids: Optional[List[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )]] = Field(\n        None, alias='role-ids'\n    )\n    authorized_privileges: Optional[List[AuthorizedPrivilege]] = Field(None, alias='authorized-privileges')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.authorized_privileges","title":"authorized_privileges: List[trestle.oscal.common.AuthorizedPrivilege] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.description","title":"description: str pydantic-field","text":"

                                                                            A summary of the user's purpose within the system.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.role_ids","title":"role_ids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.short_name","title":"short_name: ConstrainedStrValue pydantic-field","text":"

                                                                            A short common name, abbreviation, or acronym for the user.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.title","title":"title: str pydantic-field","text":"

                                                                            A name given to the user, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this user class elsewhere in this or other OSCAL instances. The locally defined UUID of the system user can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.SystemUser.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task","title":" Task (OscalBaseModel) pydantic-model","text":"

                                                                            Represents a scheduled event or milestone, which may be associated with a series of assessment actions.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Task(OscalBaseModel):\n\"\"\"\n    Represents a scheduled event or milestone, which may be associated with a series of assessment actions.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this task elsewhere in this or other OSCAL instances. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Task Universally Unique Identifier',\n    )\n    type: Union[TokenDatatype, TaskValidValues] = Field(..., description='The type of task.', title='Task Type')\n    title: str = Field(..., description='The title for this task.', title='Task Title')\n    description: Optional[str] = Field(\n        None, description='A human-readable description of this task.', title='Task Description'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    timing: Optional[Timing] = Field(\n        None, description='The timing under which the task is intended to occur.', title='Event Timing'\n    )\n    dependencies: Optional[List[Dependency]] = Field(None)\n    tasks: Optional[List[Task]] = None\n    associated_activities: Optional[List[AssociatedActivity]] = Field(None, alias='associated-activities')\n    subjects: Optional[List[AssessmentSubject]] = Field(None)\n    responsible_roles: Optional[List[ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.associated_activities","title":"associated_activities: List[trestle.oscal.common.AssociatedActivity] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.dependencies","title":"dependencies: List[trestle.oscal.common.Dependency] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.description","title":"description: str pydantic-field","text":"

                                                                            A human-readable description of this task.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.subjects","title":"subjects: List[trestle.oscal.common.AssessmentSubject] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.tasks","title":"tasks: List[trestle.oscal.common.Task] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.timing","title":"timing: Timing pydantic-field","text":"

                                                                            The timing under which the task is intended to occur.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.title","title":"title: str pydantic-field required","text":"

                                                                            The title for this task.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.type","title":"type: Union[trestle.oscal.common.TokenDatatype, trestle.oscal.common.TaskValidValues] pydantic-field required","text":"

                                                                            The type of task.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this task elsewhere in this or other OSCAL instances. The locally defined UUID of the task can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Task.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TaskValidValues","title":" TaskValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class TaskValidValues(Enum):\n    milestone = 'milestone'\n    action = 'action'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TaskValidValues.action","title":"action","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TaskValidValues.milestone","title":"milestone","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber","title":" TelephoneNumber (OscalBaseModel) pydantic-model","text":"

                                                                            A telephone service number as defined by ITU-T E.164.

                                                                            Source code in trestle/oscal/common.py
                                                                            class TelephoneNumber(OscalBaseModel):\n\"\"\"\n    A telephone service number as defined by ITU-T E.164.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    type: Optional[Union[StringDatatype, TelephoneTypeValidValues]] = Field(\n        None, description='Indicates the type of phone number.', title='type flag'\n    )\n    number: constr(regex=r'^\\S(.*\\S)?$')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.number","title":"number: ConstrainedStrValue pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.type","title":"type: Union[trestle.oscal.common.StringDatatype, trestle.oscal.common.TelephoneTypeValidValues] pydantic-field","text":"

                                                                            Indicates the type of phone number.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneNumber.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues","title":" TelephoneTypeValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class TelephoneTypeValidValues(Enum):\n    home = 'home'\n    office = 'office'\n    mobile = 'mobile'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues.home","title":"home","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues.mobile","title":"mobile","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TelephoneTypeValidValues.office","title":"office","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test","title":" Test (OscalBaseModel) pydantic-model","text":"

                                                                            A test expression which is expected to be evaluated by a tool.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Test(OscalBaseModel):\n\"\"\"\n    A test expression which is expected to be evaluated by a tool.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    expression: constr(\n        regex=r'^\\S(.*\\S)?$'\n    ) = Field(..., description='A formal (executable) expression of a constraint.', title='Constraint test')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.expression","title":"expression: ConstrainedStrValue pydantic-field required","text":"

                                                                            A formal (executable) expression of a constraint.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Test.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId","title":" ThreatId (OscalBaseModel) pydantic-model","text":"

                                                                            A pointer, by ID, to an externally-defined threat.

                                                                            Source code in trestle/oscal/common.py
                                                                            class ThreatId(OscalBaseModel):\n\"\"\"\n    A pointer, by ID, to an externally-defined threat.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    system: Union[URIDatatype, ThreatIdValidValues] = Field(\n        ..., description='Specifies the source of the threat information.', title='Threat Type Identification System'\n    )\n    href: Optional[str] = Field(\n        None,\n        description='An optional location for the threat data, from which this ID originates.',\n        title='Threat Information Resource Reference'\n    )\n    id: AnyUrl\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.href","title":"href: str pydantic-field","text":"

                                                                            An optional location for the threat data, from which this ID originates.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.id","title":"id: AnyUrl pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.system","title":"system: Union[trestle.oscal.common.URIDatatype, trestle.oscal.common.ThreatIdValidValues] pydantic-field required","text":"

                                                                            Specifies the source of the threat information.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatId.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatIdValidValues","title":" ThreatIdValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class ThreatIdValidValues(Enum):\n    http___fedramp_gov = 'http://fedramp.gov'\n    http___fedramp_gov_ns_oscal = 'http://fedramp.gov/ns/oscal'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatIdValidValues.http___fedramp_gov","title":"http___fedramp_gov","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.ThreatIdValidValues.http___fedramp_gov_ns_oscal","title":"http___fedramp_gov_ns_oscal","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues","title":" TimeUnitValidValues (Enum) ","text":"Source code in trestle/oscal/common.py
                                                                            class TimeUnitValidValues(Enum):\n    seconds = 'seconds'\n    minutes = 'minutes'\n    hours = 'hours'\n    days = 'days'\n    months = 'months'\n    years = 'years'\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.days","title":"days","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.hours","title":"hours","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.minutes","title":"minutes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.months","title":"months","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.seconds","title":"seconds","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TimeUnitValidValues.years","title":"years","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing","title":" Timing (OscalBaseModel) pydantic-model","text":"

                                                                            The timing under which the task is intended to occur.

                                                                            Source code in trestle/oscal/common.py
                                                                            class Timing(OscalBaseModel):\n\"\"\"\n    The timing under which the task is intended to occur.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    on_date: Optional[OnDate] = Field(\n        None,\n        alias='on-date',\n        description='The task is intended to occur on the specified date.',\n        title='On Date Condition'\n    )\n    within_date_range: Optional[WithinDateRange] = Field(\n        None,\n        alias='within-date-range',\n        description='The task is intended to occur within the specified date range.',\n        title='On Date Range Condition'\n    )\n    at_frequency: Optional[AtFrequency] = Field(\n        None,\n        alias='at-frequency',\n        description='The task is intended to occur at the specified frequency.',\n        title='Frequency Condition'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.at_frequency","title":"at_frequency: AtFrequency pydantic-field","text":"

                                                                            The task is intended to occur at the specified frequency.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.on_date","title":"on_date: OnDate pydantic-field","text":"

                                                                            The task is intended to occur on the specified date.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.within_date_range","title":"within_date_range: WithinDateRange pydantic-field","text":"

                                                                            The task is intended to occur within the specified date range.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Timing.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype","title":" TokenDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class TokenDatatype(OscalBaseModel):\n    __root__: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        description=\n        'A non-colonized name as defined by XML Schema Part 2: Datatypes Second Edition. https://www.w3.org/TR/xmlschema11-2/#NCName.'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            A non-colonized name as defined by XML Schema Part 2: Datatypes Second Edition. https://www.w3.org/TR/xmlschema11-2/#NCName.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.TokenDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype","title":" URIDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class URIDatatype(OscalBaseModel):\n    __root__: AnyUrl = Field(..., description='A universal resource identifier (URI) formatted according to RFC3986.')\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__root__","title":"__root__: AnyUrl pydantic-field required special","text":"

                                                                            A universal resource identifier (URI) formatted according to RFC3986.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype","title":" URIReferenceDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class URIReferenceDatatype(OscalBaseModel):\n    __root__: str = Field(\n        ...,\n        description=\n        'A URI Reference, either a URI or a relative-reference, formatted according to section 4.1 of RFC3986.'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__root__","title":"__root__: str pydantic-field required special","text":"

                                                                            A URI Reference, either a URI or a relative-reference, formatted according to section 4.1 of RFC3986.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.URIReferenceDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype","title":" UUIDDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class UUIDDatatype(OscalBaseModel):\n    __root__: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(..., description=\"A type 4 ('random' or 'pseudorandom') or type 5 UUID per RFC 4122.\")\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            A type 4 ('random' or 'pseudorandom') or type 5 UUID per RFC 4122.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UUIDDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent","title":" UsesComponent (OscalBaseModel) pydantic-model","text":"

                                                                            The set of components that are used by the assessment platform.

                                                                            Source code in trestle/oscal/common.py
                                                                            class UsesComponent(OscalBaseModel):\n\"\"\"\n    The set of components that are used by the assessment platform.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description=\n        'A machine-oriented identifier reference to a component that is implemented as part of an inventory item.',\n        title='Component Universally Unique Identifier Reference'\n    )\n    props: Optional[List[Property]] = Field(None)\n    links: Optional[List[Link]] = Field(None)\n    responsible_parties: Optional[List[ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a component that is implemented as part of an inventory item.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.UsesComponent.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version","title":" Version (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/common.py
                                                                            class Version(OscalBaseModel):\n    __root__: StringDatatype = Field(\n        ...,\n        description=\n        'Used to distinguish a specific revision of an OSCAL document from other previous and future versions.',\n        title='Document Version'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__root__","title":"__root__: StringDatatype pydantic-field required special","text":"

                                                                            Used to distinguish a specific revision of an OSCAL document from other previous and future versions.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.Version.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange","title":" WithinDateRange (OscalBaseModel) pydantic-model","text":"

                                                                            The task is intended to occur within the specified date range.

                                                                            Source code in trestle/oscal/common.py
                                                                            class WithinDateRange(OscalBaseModel):\n\"\"\"\n    The task is intended to occur within the specified date range.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    start: datetime = Field(\n        ..., description='The task must occur on or after the specified date.', title='Start Date Condition'\n    )\n    end: datetime = Field(\n        ..., description='The task must occur on or before the specified date.', title='End Date Condition'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.end","title":"end: datetime pydantic-field required","text":"

                                                                            The task must occur on or before the specified date.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.start","title":"start: datetime pydantic-field required","text":"

                                                                            The task must occur on or after the specified date.

                                                                            "},{"location":"api_reference/trestle.oscal.common/#trestle.oscal.common.WithinDateRange.Config","title":" Config ","text":"Source code in trestle/oscal/common.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/","title":"component","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component","title":"trestle.oscal.component","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability","title":" Capability (OscalBaseModel) pydantic-model","text":"

                                                                            A grouping of other components and/or capabilities.

                                                                            Source code in trestle/oscal/component.py
                                                                            class Capability(OscalBaseModel):\n\"\"\"\n    A grouping of other components and/or capabilities.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given capability.',\n                     title='Capability Identifier'\n                 )\n    name: constr(regex=r'^\\S(.*\\S)?$'\n                 ) = Field(..., description=\"The capability's human-readable name.\", title='Capability Name')\n    description: str = Field(..., description='A summary of the capability.', title='Capability Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    incorporates_components: Optional[List[IncorporatesComponent]] = Field(None, alias='incorporates-components')\n    control_implementations: Optional[List[ControlImplementation]] = Field(None, alias='control-implementations')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.control_implementations","title":"control_implementations: List[trestle.oscal.component.ControlImplementation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of the capability.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.incorporates_components","title":"incorporates_components: List[trestle.oscal.component.IncorporatesComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.name","title":"name: ConstrainedStrValue pydantic-field required","text":"

                                                                            The capability's human-readable name.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            Provides a globally unique means to identify a given capability.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Capability.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition","title":" ComponentDefinition (OscalBaseModel) pydantic-model","text":"

                                                                            A collection of component descriptions, which may optionally be grouped by capability.

                                                                            Source code in trestle/oscal/component.py
                                                                            class ComponentDefinition(OscalBaseModel):\n\"\"\"\n    A collection of component descriptions, which may optionally be grouped by capability.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given component definition instance.',\n                     title='Component Definition Universally Unique Identifier'\n                 )\n    metadata: common.Metadata\n    import_component_definitions: Optional[List[ImportComponentDefinition]] = Field(\n        None, alias='import-component-definitions'\n    )\n    components: Optional[List[DefinedComponent]] = Field(None)\n    capabilities: Optional[List[Capability]] = Field(None)\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.capabilities","title":"capabilities: List[trestle.oscal.component.Capability] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.components","title":"components: List[trestle.oscal.component.DefinedComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.import_component_definitions","title":"import_component_definitions: List[trestle.oscal.component.ImportComponentDefinition] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            Provides a globally unique means to identify a given component definition instance.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ComponentDefinition.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation","title":" ControlImplementation (OscalBaseModel) pydantic-model","text":"

                                                                            Defines how the component or capability supports a set of controls.

                                                                            Source code in trestle/oscal/component.py
                                                                            class ControlImplementation(OscalBaseModel):\n\"\"\"\n    Defines how the component or capability supports a set of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'Provides a means to identify a set of control implementations that are supported by a given component or capability.',\n        title='Control Implementation Set Identifier'\n    )\n    source: str = Field(\n        ...,\n        description=\n        'A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.',\n        title='Source Resource Reference'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'A description of how the specified set of controls are implemented for the containing component or capability.',\n        title='Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    implemented_requirements: List[ImplementedRequirement] = Field(..., alias='implemented-requirements')\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.description","title":"description: str pydantic-field required","text":"

                                                                            A description of how the specified set of controls are implemented for the containing component or capability.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.implemented_requirements","title":"implemented_requirements: List[trestle.oscal.component.ImplementedRequirement] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.set_parameters","title":"set_parameters: List[trestle.oscal.component.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.source","title":"source: str pydantic-field required","text":"

                                                                            A reference to an OSCAL catalog or profile providing the referenced control or subcontrol definition.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            Provides a means to identify a set of control implementations that are supported by a given component or capability.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ControlImplementation.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent","title":" DefinedComponent (OscalBaseModel) pydantic-model","text":"

                                                                            A defined component that can be part of an implemented system.

                                                                            Source code in trestle/oscal/component.py
                                                                            class DefinedComponent(OscalBaseModel):\n\"\"\"\n    A defined component that can be part of an implemented system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given component.',\n                     title='Component Identifier'\n                 )\n    type: Union[constr(regex=r'^\\S(.*\\S)?$'), DefinedComponentTypeValidValues] = Field(\n        ..., description='A category describing the purpose of the component.', title='Component Type'\n    )\n    title: str = Field(..., description='A human readable name for the component.', title='Component Title')\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description'\n    )\n    purpose: Optional[str] = Field(\n        None, description='A summary of the technological or business purpose of the component.', title='Purpose'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    protocols: Optional[List[common.Protocol]] = Field(None)\n    control_implementations: Optional[List[ControlImplementation]] = Field(None, alias='control-implementations')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.control_implementations","title":"control_implementations: List[trestle.oscal.component.ControlImplementation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.description","title":"description: str pydantic-field required","text":"

                                                                            A description of the component, including information about its function.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.protocols","title":"protocols: List[trestle.oscal.common.Protocol] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.purpose","title":"purpose: str pydantic-field","text":"

                                                                            A summary of the technological or business purpose of the component.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.title","title":"title: str pydantic-field required","text":"

                                                                            A human readable name for the component.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.type","title":"type: Union[pydantic.v1.types.ConstrainedStrValue, trestle.oscal.component.DefinedComponentTypeValidValues] pydantic-field required","text":"

                                                                            A category describing the purpose of the component.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            Provides a globally unique means to identify a given component.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponent.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues","title":" DefinedComponentTypeValidValues (Enum) ","text":"Source code in trestle/oscal/component.py
                                                                            class DefinedComponentTypeValidValues(Enum):\n    interconnection = 'interconnection'\n    software = 'software'\n    hardware = 'hardware'\n    service = 'service'\n    policy = 'policy'\n    physical = 'physical'\n    process_procedure = 'process-procedure'\n    plan = 'plan'\n    guidance = 'guidance'\n    standard = 'standard'\n    validation = 'validation'\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.guidance","title":"guidance","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.hardware","title":"hardware","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.interconnection","title":"interconnection","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.physical","title":"physical","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.plan","title":"plan","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.policy","title":"policy","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.process_procedure","title":"process_procedure","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.service","title":"service","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.software","title":"software","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.standard","title":"standard","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.DefinedComponentTypeValidValues.validation","title":"validation","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement","title":" ImplementedRequirement (OscalBaseModel) pydantic-model","text":"

                                                                            Describes how the containing component or capability implements an individual control.

                                                                            Source code in trestle/oscal/component.py
                                                                            class ImplementedRequirement(OscalBaseModel):\n\"\"\"\n    Describes how the containing component or capability implements an individual control.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description='Provides a globally unique means to identify a given control implementation by a component.',\n        title='Control Implementation Identifier'\n    )\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'A suggestion from the supplier (e.g., component vendor or author) for how the specified control may be implemented if the containing component or capability is instantiated in a system security plan.',\n        title='Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    statements: Optional[List[Statement]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.description","title":"description: str pydantic-field required","text":"

                                                                            A suggestion from the supplier (e.g., component vendor or author) for how the specified control may be implemented if the containing component or capability is instantiated in a system security plan.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.set_parameters","title":"set_parameters: List[trestle.oscal.component.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.statements","title":"statements: List[trestle.oscal.component.Statement] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            Provides a globally unique means to identify a given control implementation by a component.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImplementedRequirement.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition","title":" ImportComponentDefinition (OscalBaseModel) pydantic-model","text":"

                                                                            Loads a component definition from another resource.

                                                                            Source code in trestle/oscal/component.py
                                                                            class ImportComponentDefinition(OscalBaseModel):\n\"\"\"\n    Loads a component definition from another resource.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description=\n        'A link to a resource that defines a set of components and/or capabilities to import into this collection.',\n        title='Hyperlink Reference'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.href","title":"href: str pydantic-field required","text":"

                                                                            A link to a resource that defines a set of components and/or capabilities to import into this collection.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.ImportComponentDefinition.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent","title":" IncorporatesComponent (OscalBaseModel) pydantic-model","text":"

                                                                            The collection of components comprising this capability.

                                                                            Source code in trestle/oscal/component.py
                                                                            class IncorporatesComponent(OscalBaseModel):\n\"\"\"\n    The collection of components comprising this capability.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description='A machine-oriented identifier reference to a component.',\n        title='Component Reference'\n    )\n    description: str = Field(\n        ...,\n        description='A description of the component, including information about its function.',\n        title='Component Description'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a component.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.description","title":"description: str pydantic-field required","text":"

                                                                            A description of the component, including information about its function.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.IncorporatesComponent.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/component.py
                                                                            class Model(OscalBaseModel):\n    component_definition: ComponentDefinition = Field(..., alias='component-definition')\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Model.component_definition","title":"component_definition: ComponentDefinition pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter","title":" SetParameter (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the parameter that will be set by the enclosed value.

                                                                            Source code in trestle/oscal/component.py
                                                                            class SetParameter(OscalBaseModel):\n\"\"\"\n    Identifies the parameter that will be set by the enclosed value.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    param_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='param-id',\n        description=\n        \"A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.\",\n        title='Parameter ID'\n    )\n    values: List[constr(regex=r'^\\S(.*\\S)?$')] = Field(...)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.SetParameter.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement","title":" Statement (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies which statements within a control are addressed.

                                                                            Source code in trestle/oscal/component.py
                                                                            class Statement(OscalBaseModel):\n\"\"\"\n    Identifies which statements within a control are addressed.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    statement_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='statement-id',\n        description='A human-oriented identifier reference to a control statement.',\n        title='Control Statement Reference'\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).',\n        title='Control Statement Reference Universally Unique Identifier'\n    )\n    description: str = Field(\n        ...,\n        description='A summary of how the containing control statement is implemented by the component or capability.',\n        title='Statement Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of how the containing control statement is implemented by the component or capability.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.statement_id","title":"statement_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented identifier reference to a control statement.

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).

                                                                            "},{"location":"api_reference/trestle.oscal.component/#trestle.oscal.component.Statement.Config","title":" Config ","text":"Source code in trestle/oscal/component.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/","title":"poam","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam","title":"trestle.oscal.poam","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions","title":" LocalDefinitions (OscalBaseModel) pydantic-model","text":"

                                                                            Allows components, and inventory-items to be defined within the POA&M for circumstances where no OSCAL-based SSP exists, or is not delivered with the POA&M.

                                                                            Source code in trestle/oscal/poam.py
                                                                            class LocalDefinitions(OscalBaseModel):\n\"\"\"\n    Allows components, and inventory-items to be defined within the POA&M for circumstances where no OSCAL-based SSP exists, or is not delivered with the POA&M.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    components: Optional[List[common.SystemComponent]] = Field(None)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    assessment_assets: Optional[common.AssessmentAssets] = Field(None, alias='assessment-assets')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.assessment_assets","title":"assessment_assets: AssessmentAssets pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.LocalDefinitions.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/poam.py
                                                                            class Model(OscalBaseModel):\n    plan_of_action_and_milestones: PlanOfActionAndMilestones = Field(..., alias='plan-of-action-and-milestones')\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Model.plan_of_action_and_milestones","title":"plan_of_action_and_milestones: PlanOfActionAndMilestones pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination","title":" Origination (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the source of the finding, such as a tool or person.

                                                                            Source code in trestle/oscal/poam.py
                                                                            class Origination(OscalBaseModel):\n\"\"\"\n    Identifies the source of the finding, such as a tool or person.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    actors: List[common.OriginActor] = Field(...)\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.actors","title":"actors: List[trestle.oscal.common.OriginActor] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.Origination.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones","title":" PlanOfActionAndMilestones (OscalBaseModel) pydantic-model","text":"

                                                                            A plan of action and milestones which identifies initial and residual risks, deviations, and disposition, such as those required by FedRAMP.

                                                                            Source code in trestle/oscal/poam.py
                                                                            class PlanOfActionAndMilestones(OscalBaseModel):\n\"\"\"\n    A plan of action and milestones which identifies initial and residual risks, deviations, and disposition, such as those required by FedRAMP.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with instancescope that can be used to reference this POA&M instance in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='POA&M Universally Unique Identifier'\n    )\n    metadata: common.Metadata\n    import_ssp: Optional[common.ImportSsp] = Field(None, alias='import-ssp')\n    system_id: Optional[common.SystemId] = Field(None, alias='system-id')\n    local_definitions: Optional[LocalDefinitions] = Field(None, alias='local-definitions')\n    observations: Optional[List[common.Observation]] = Field(None)\n    risks: Optional[List[common.Risk]] = Field(None)\n    findings: Optional[List[common.Finding]] = Field(None)\n    poam_items: List[PoamItem] = Field(..., alias='poam-items')\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.findings","title":"findings: List[trestle.oscal.common.Finding] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.import_ssp","title":"import_ssp: ImportSsp pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.local_definitions","title":"local_definitions: LocalDefinitions pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.observations","title":"observations: List[trestle.oscal.common.Observation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.poam_items","title":"poam_items: List[trestle.oscal.poam.PoamItem] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.risks","title":"risks: List[trestle.oscal.common.Risk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.system_id","title":"system_id: SystemId pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with instancescope that can be used to reference this POA&M instance in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PlanOfActionAndMilestones.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem","title":" PoamItem (OscalBaseModel) pydantic-model","text":"

                                                                            Describes an individual POA&M item.

                                                                            Source code in trestle/oscal/poam.py
                                                                            class PoamItem(OscalBaseModel):\n\"\"\"\n    Describes an individual POA&M item.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with instance scope that can be used to reference this POA&M item entry in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='POA&M Item Universally Unique Identifier'\n    )\n    title: str = Field(..., description='The title or name for this POA&M item .', title='POA&M Item Title')\n    description: str = Field(\n        ..., description='A human-readable description of POA&M item.', title='POA&M Item Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    related_findings: Optional[List[RelatedFinding]] = Field(None, alias='related-findings')\n    related_observations: Optional[List[common.RelatedObservation]] = Field(None, alias='related-observations')\n    related_risks: Optional[List[common.RelatedRisk]] = Field(None, alias='related-risks')\n    remarks: Optional[str] = None\n    origins: Optional[List[Origination]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.description","title":"description: str pydantic-field required","text":"

                                                                            A human-readable description of POA&M item.

                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.origins","title":"origins: List[trestle.oscal.poam.Origination] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.related_findings","title":"related_findings: List[trestle.oscal.poam.RelatedFinding] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.related_observations","title":"related_observations: List[trestle.oscal.common.RelatedObservation] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.related_risks","title":"related_risks: List[trestle.oscal.common.RelatedRisk] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.title","title":"title: str pydantic-field required","text":"

                                                                            The title or name for this POA&M item .

                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented, globally unique identifier with instance scope that can be used to reference this POA&M item entry in this OSCAL instance. This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.PoamItem.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding","title":" RelatedFinding (OscalBaseModel) pydantic-model","text":"

                                                                            Relates the finding to referenced finding(s).

                                                                            Source code in trestle/oscal/poam.py
                                                                            class RelatedFinding(OscalBaseModel):\n\"\"\"\n    Relates the finding to referenced finding(s).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    finding_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='finding-uuid',\n        description='A machine-oriented identifier reference to a finding defined in the list of findings.',\n        title='Finding Universally Unique Identifier Reference'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.finding_uuid","title":"finding_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to a finding defined in the list of findings.

                                                                            "},{"location":"api_reference/trestle.oscal.poam/#trestle.oscal.poam.RelatedFinding.Config","title":" Config ","text":"Source code in trestle/oscal/poam.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/","title":"profile","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile","title":"trestle.oscal.profile","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add","title":" Add (OscalBaseModel) pydantic-model","text":"

                                                                            Specifies contents to be added into controls, in resolution.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Add(OscalBaseModel):\n\"\"\"\n    Specifies contents to be added into controls, in resolution.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    position: Optional[PositionValidValues] = Field(\n        None,\n        description='Where to add the new content with respect to the targeted element (beside it or inside it).',\n        title='Position'\n    )\n    by_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, alias='by-id', description='Target location of the addition.', title='Reference by ID'\n    )\n    title: Optional[str] = Field(\n        None,\n        description='A name given to the control, which may be used by a tool for display and navigation.',\n        title='Title Change'\n    )\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.by_id","title":"by_id: ConstrainedStrValue pydantic-field","text":"

                                                                            Target location of the addition.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.position","title":"position: PositionValidValues pydantic-field","text":"

                                                                            Where to add the new content with respect to the targeted element (beside it or inside it).

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.title","title":"title: str pydantic-field","text":"

                                                                            A name given to the control, which may be used by a tool for display and navigation.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Add.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter","title":" Alter (OscalBaseModel) pydantic-model","text":"

                                                                            Specifies changes to be made to an included control when a profile is resolved.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Alter(OscalBaseModel):\n\"\"\"\n    Specifies changes to be made to an included control when a profile is resolved.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    removes: Optional[List[Remove]] = Field(None)\n    adds: Optional[List[Add]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.adds","title":"adds: List[trestle.oscal.profile.Add] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.removes","title":"removes: List[trestle.oscal.profile.Remove] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Alter.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype","title":" BooleanDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/profile.py
                                                                            class BooleanDatatype(OscalBaseModel):\n    __root__: bool = Field(..., description='A binary value that is either: true or false.')\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__root__","title":"__root__: bool pydantic-field required special","text":"

                                                                            A binary value that is either: true or false.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.BooleanDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues","title":" CombinationMethodValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                                                            class CombinationMethodValidValues(Enum):\n    use_first = 'use-first'\n    merge = 'merge'\n    keep = 'keep'\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues.keep","title":"keep","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues.merge","title":"merge","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.CombinationMethodValidValues.use_first","title":"use_first","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine","title":" Combine (OscalBaseModel) pydantic-model","text":"

                                                                            A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Combine(OscalBaseModel):\n\"\"\"\n    A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    method: Optional[CombinationMethodValidValues] = Field(\n        None, description='Declare how clashing controls should be handled.', title='Combination Method'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.method","title":"method: CombinationMethodValidValues pydantic-field","text":"

                                                                            Declare how clashing controls should be handled.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Combine.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom","title":" Custom (OscalBaseModel) pydantic-model","text":"

                                                                            Provides an alternate grouping structure that selected controls will be placed in.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Custom(OscalBaseModel):\n\"\"\"\n    Provides an alternate grouping structure that selected controls will be placed in.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    groups: Optional[List[Group]] = Field(None)\n    insert_controls: Optional[List[InsertControls]] = Field(None, alias='insert-controls')\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.groups","title":"groups: List[trestle.oscal.profile.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.insert_controls","title":"insert_controls: List[trestle.oscal.profile.InsertControls] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Custom.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group","title":" Group (OscalBaseModel) pydantic-model","text":"

                                                                            A group of (selected) controls or of groups of controls.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Group(OscalBaseModel):\n\"\"\"\n    A group of (selected) controls or of groups of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, description='Identifies the group.', title='Group Identifier'\n    )\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a sub-type or characterization of the group.',\n        title='Group Class'\n    )\n    title: str = Field(..., description='A name to be given to the group for use in display.', title='Group Title')\n    params: Optional[List[common.Parameter]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    parts: Optional[List[common.Part]] = Field(None)\n    groups: Optional[List[Group]] = None\n    insert_controls: Optional[List[InsertControls]] = Field(None, alias='insert-controls')\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            A textual label that provides a sub-type or characterization of the group.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.groups","title":"groups: List[trestle.oscal.profile.Group] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.id","title":"id: ConstrainedStrValue pydantic-field","text":"

                                                                            Identifies the group.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.insert_controls","title":"insert_controls: List[trestle.oscal.profile.InsertControls] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.params","title":"params: List[trestle.oscal.common.Parameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.parts","title":"parts: List[trestle.oscal.common.Part] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.title","title":"title: str pydantic-field required","text":"

                                                                            A name to be given to the group for use in display.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Group.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import","title":" Import (OscalBaseModel) pydantic-model","text":"

                                                                            Designates a referenced source catalog or profile that provides a source of control information for use in creating a new overlay or baseline.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Import(OscalBaseModel):\n\"\"\"\n    Designates a referenced source catalog or profile that provides a source of control information for use in creating a new overlay or baseline.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description='A resolvable URL reference to the base catalog or profile that this profile is tailoring.',\n        title='Catalog or Profile Reference'\n    )\n    include_all: Optional[common.IncludeAll] = Field(None, alias='include-all')\n    include_controls: Optional[List[SelectControl]] = Field(None, alias='include-controls')\n    exclude_controls: Optional[List[SelectControl]] = Field(None, alias='exclude-controls')\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.exclude_controls","title":"exclude_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.href","title":"href: str pydantic-field required","text":"

                                                                            A resolvable URL reference to the base catalog or profile that this profile is tailoring.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.include_controls","title":"include_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Import.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls","title":" InsertControls (OscalBaseModel) pydantic-model","text":"

                                                                            Specifies which controls to use in the containing context.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class InsertControls(OscalBaseModel):\n\"\"\"\n    Specifies which controls to use in the containing context.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    order: Optional[OrderValidValues] = Field(\n        None, description='A designation of how a selection of controls in a profile is to be ordered.', title='Order'\n    )\n    include_all: Optional[common.IncludeAll] = Field(None, alias='include-all')\n    include_controls: Optional[List[SelectControl]] = Field(None, alias='include-controls')\n    exclude_controls: Optional[List[SelectControl]] = Field(None, alias='exclude-controls')\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.exclude_controls","title":"exclude_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.include_all","title":"include_all: IncludeAll pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.include_controls","title":"include_controls: List[trestle.oscal.profile.SelectControl] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.order","title":"order: OrderValidValues pydantic-field","text":"

                                                                            A designation of how a selection of controls in a profile is to be ordered.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.InsertControls.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues","title":" ItemNameValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                                                            class ItemNameValidValues(Enum):\n    param = 'param'\n    prop = 'prop'\n    link = 'link'\n    part = 'part'\n    mapping = 'mapping'\n    map = 'map'\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.link","title":"link","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.map","title":"map","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.mapping","title":"mapping","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.param","title":"param","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.part","title":"part","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.ItemNameValidValues.prop","title":"prop","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching","title":" Matching (OscalBaseModel) pydantic-model","text":"

                                                                            Selecting a set of controls by matching their IDs with a wildcard pattern.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Matching(OscalBaseModel):\n\"\"\"\n    Selecting a set of controls by matching their IDs with a wildcard pattern.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    pattern: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None, description='A glob expression matching the IDs of one or more controls to be selected.', title='Pattern'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.pattern","title":"pattern: ConstrainedStrValue pydantic-field","text":"

                                                                            A glob expression matching the IDs of one or more controls to be selected.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Matching.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge","title":" Merge (OscalBaseModel) pydantic-model","text":"

                                                                            Provides structuring directives that instruct how controls are organized after profile resolution.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Merge(OscalBaseModel):\n\"\"\"\n    Provides structuring directives that instruct how controls are organized after profile resolution.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    combine: Optional[Combine] = Field(\n        None,\n        description=\n        'A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).',\n        title='Combination Rule'\n    )\n    flat: Optional[Dict[str, Any]] = Field(\n        None, description='Directs that controls appear without any grouping structure.', title='Flat Without Grouping'\n    )\n    as_is: Optional[BooleanDatatype] = Field(\n        None,\n        alias='as-is',\n        description=\n        'Indicates that the controls selected should retain their original grouping as defined in the import source.',\n        title='Group As-Is'\n    )\n    custom: Optional[Custom] = Field(\n        None,\n        description='Provides an alternate grouping structure that selected controls will be placed in.',\n        title='Custom Grouping'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.as_is","title":"as_is: BooleanDatatype pydantic-field","text":"

                                                                            Indicates that the controls selected should retain their original grouping as defined in the import source.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.combine","title":"combine: Combine pydantic-field","text":"

                                                                            A Combine element defines how to resolve duplicate instances of the same control (e.g., controls with the same ID).

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.custom","title":"custom: Custom pydantic-field","text":"

                                                                            Provides an alternate grouping structure that selected controls will be placed in.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.flat","title":"flat: Dict[str, Any] pydantic-field","text":"

                                                                            Directs that controls appear without any grouping structure.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Merge.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/profile.py
                                                                            class Model(OscalBaseModel):\n    profile: Profile\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Model.profile","title":"profile: Profile pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify","title":" Modify (OscalBaseModel) pydantic-model","text":"

                                                                            Set parameters or amend controls in resolution.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Modify(OscalBaseModel):\n\"\"\"\n    Set parameters or amend controls in resolution.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    alters: Optional[List[Alter]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.alters","title":"alters: List[trestle.oscal.profile.Alter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.set_parameters","title":"set_parameters: List[trestle.oscal.profile.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Modify.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues","title":" OrderValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                                                            class OrderValidValues(Enum):\n    keep = 'keep'\n    ascending = 'ascending'\n    descending = 'descending'\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues.ascending","title":"ascending","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues.descending","title":"descending","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.OrderValidValues.keep","title":"keep","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues","title":" PositionValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                                                            class PositionValidValues(Enum):\n    before = 'before'\n    after = 'after'\n    starting = 'starting'\n    ending = 'ending'\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.after","title":"after","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.before","title":"before","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.ending","title":"ending","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.PositionValidValues.starting","title":"starting","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile","title":" Profile (OscalBaseModel) pydantic-model","text":"

                                                                            Each OSCAL profile is defined by a profile element.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Profile(OscalBaseModel):\n\"\"\"\n    Each OSCAL profile is defined by a profile element.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n                 ) = Field(\n                     ...,\n                     description='Provides a globally unique means to identify a given profile instance.',\n                     title='Profile Universally Unique Identifier'\n                 )\n    metadata: common.Metadata\n    imports: List[Import] = Field(...)\n    merge: Optional[Merge] = None\n    modify: Optional[Modify] = None\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.imports","title":"imports: List[trestle.oscal.profile.Import] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.merge","title":"merge: Merge pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.modify","title":"modify: Modify pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            Provides a globally unique means to identify a given profile instance.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Profile.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove","title":" Remove (OscalBaseModel) pydantic-model","text":"

                                                                            Specifies objects to be removed from a control based on specific aspects of the object that must all match.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class Remove(OscalBaseModel):\n\"\"\"\n    Specifies objects to be removed from a control based on specific aspects of the object that must all match.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    by_name: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='by-name',\n        description='Identify items remove by matching their assigned name.',\n        title='Reference by (assigned) name'\n    )\n    by_class: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='by-class',\n        description='Identify items to remove by matching their class.',\n        title='Reference by class'\n    )\n    by_id: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None, alias='by-id', description='Identify items to remove indicated by their id.', title='Reference by ID'\n    )\n    by_item_name: Optional[ItemNameValidValues] = Field(\n        None,\n        alias='by-item-name',\n        description=\"Identify items to remove by the name of the item's information object name, e.g. title or prop.\",\n        title='Item Name Reference'\n    )\n    by_ns: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='by-ns',\n        description=\"Identify items to remove by the item's ns, which is the namespace associated with a part, or prop.\",\n        title='Item Namespace Reference'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_class","title":"by_class: ConstrainedStrValue pydantic-field","text":"

                                                                            Identify items to remove by matching their class.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_id","title":"by_id: ConstrainedStrValue pydantic-field","text":"

                                                                            Identify items to remove indicated by their id.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_item_name","title":"by_item_name: ItemNameValidValues pydantic-field","text":"

                                                                            Identify items to remove by the name of the item's information object name, e.g. title or prop.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_name","title":"by_name: ConstrainedStrValue pydantic-field","text":"

                                                                            Identify items remove by matching their assigned name.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.by_ns","title":"by_ns: ConstrainedStrValue pydantic-field","text":"

                                                                            Identify items to remove by the item's ns, which is the namespace associated with a part, or prop.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.Remove.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl","title":" SelectControl (OscalBaseModel) pydantic-model","text":"

                                                                            Select a control or controls from an imported control set.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class SelectControl(OscalBaseModel):\n\"\"\"\n    Select a control or controls from an imported control set.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    with_child_controls: Optional[WithChildControlsValidValues] = Field(\n        None,\n        alias='with-child-controls',\n        description='When a control is included, whether its child (dependent) controls are also included.',\n        title='Include Contained Controls with Control'\n    )\n    with_ids: Optional[List[WithId]] = Field(None, alias='with-ids')\n    matching: Optional[List[Matching]] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.matching","title":"matching: List[trestle.oscal.profile.Matching] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.with_child_controls","title":"with_child_controls: WithChildControlsValidValues pydantic-field","text":"

                                                                            When a control is included, whether its child (dependent) controls are also included.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.with_ids","title":"with_ids: List[trestle.oscal.profile.WithId] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SelectControl.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter","title":" SetParameter (OscalBaseModel) pydantic-model","text":"

                                                                            A parameter setting, to be propagated to points of insertion.

                                                                            Source code in trestle/oscal/profile.py
                                                                            class SetParameter(OscalBaseModel):\n\"\"\"\n    A parameter setting, to be propagated to points of insertion.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    param_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(..., alias='param-id', description='An identifier for the parameter.', title='Parameter ID')\n    class_: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='class',\n        description='A textual label that provides a characterization of the parameter.',\n        title='Parameter Class'\n    )\n    depends_on: Optional[constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    )] = Field(\n        None,\n        alias='depends-on',\n        description=\n        '**(deprecated)** Another parameter invoking this one. This construct has been deprecated and should not be used.',\n        title='Depends On'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    label: Optional[str] = Field(\n        None,\n        description=\n        'A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.',\n        title='Parameter Label'\n    )\n    usage: Optional[str] = Field(\n        None, description='Describes the purpose and use of a parameter.', title='Parameter Usage Description'\n    )\n    constraints: Optional[List[common.ParameterConstraint]] = Field(None)\n    guidelines: Optional[List[common.ParameterGuideline]] = Field(None)\n    values: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None)\n    select: Optional[common.ParameterSelection] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.class_","title":"class_: ConstrainedStrValue pydantic-field","text":"

                                                                            A textual label that provides a characterization of the parameter.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.constraints","title":"constraints: List[trestle.oscal.common.ParameterConstraint] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.depends_on","title":"depends_on: ConstrainedStrValue pydantic-field","text":"

                                                                            (deprecated) Another parameter invoking this one. This construct has been deprecated and should not be used.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.guidelines","title":"guidelines: List[trestle.oscal.common.ParameterGuideline] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.label","title":"label: str pydantic-field","text":"

                                                                            A short, placeholder name for the parameter, which can be used as a substitute for a value if no value is assigned.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            An identifier for the parameter.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.select","title":"select: ParameterSelection pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.usage","title":"usage: str pydantic-field","text":"

                                                                            Describes the purpose and use of a parameter.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.SetParameter.Config","title":" Config ","text":"Source code in trestle/oscal/profile.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithChildControlsValidValues","title":" WithChildControlsValidValues (Enum) ","text":"Source code in trestle/oscal/profile.py
                                                                            class WithChildControlsValidValues(Enum):\n    yes = 'yes'\n    no = 'no'\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithChildControlsValidValues.no","title":"no","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithChildControlsValidValues.yes","title":"yes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId","title":" WithId (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/profile.py
                                                                            class WithId(OscalBaseModel):\n    __root__: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ..., description='Selecting a control by its ID given as a literal.', title='Match Controls by Identifier'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            Selecting a control by its ID given as a literal.

                                                                            "},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.profile/#trestle.oscal.profile.WithId.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/","title":"ssp","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp","title":"trestle.oscal.ssp","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp-classes","title":"Classes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification","title":" AdjustmentJustification (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                                                            class AdjustmentJustification(OscalBaseModel):\n    __root__: str = Field(\n        ...,\n        description=\n        'If the selected security level is different from the base security level, this contains the justification for the change.',\n        title='Adjustment Justification'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__root__","title":"__root__: str pydantic-field required special","text":"

                                                                            If the selected security level is different from the base security level, this contains the justification for the change.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AdjustmentJustification.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary","title":" AuthorizationBoundary (OscalBaseModel) pydantic-model","text":"

                                                                            A description of this system's authorization boundary, optionally supplemented by diagrams that illustrate the authorization boundary.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class AuthorizationBoundary(OscalBaseModel):\n\"\"\"\n    A description of this system's authorization boundary, optionally supplemented by diagrams that illustrate the authorization boundary.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(\n        ...,\n        description=\"A summary of the system's authorization boundary.\",\n        title='Authorization Boundary Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    diagrams: Optional[List[Diagram]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of the system's authorization boundary.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.diagrams","title":"diagrams: List[trestle.oscal.ssp.Diagram] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.AuthorizationBoundary.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base","title":" Base (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                                                            class Base(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description='The prescribed base (Confidentiality, Integrity, or Availability) security impact level.',\n        title='Base Level (Confidentiality, Integrity, or Availability)'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            The prescribed base (Confidentiality, Integrity, or Availability) security impact level.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Base.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent","title":" ByComponent (OscalBaseModel) pydantic-model","text":"

                                                                            Defines how the referenced component implements a set of controls.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class ByComponent(OscalBaseModel):\n\"\"\"\n    Defines how the referenced component implements a set of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    component_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='component-uuid',\n        description='A machine-oriented identifier reference to the component that is implemeting a given control.',\n        title='Component Universally Unique Identifier Reference'\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='By-Component Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes how a control or a control statement is implemented within the referenced system component.',\n        title='Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    implementation_status: Optional[common.ImplementationStatus] = Field(None, alias='implementation-status')\n    export: Optional[Export] = Field(\n        None,\n        description='Identifies content intended for external consumption, such as with leveraged organizations.',\n        title='Export'\n    )\n    inherited: Optional[List[Inherited]] = Field(None)\n    satisfied: Optional[List[Satisfied]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.component_uuid","title":"component_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to the component that is implemeting a given control.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.description","title":"description: str pydantic-field required","text":"

                                                                            An implementation statement that describes how a control or a control statement is implemented within the referenced system component.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.export","title":"export: Export pydantic-field","text":"

                                                                            Identifies content intended for external consumption, such as with leveraged organizations.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.implementation_status","title":"implementation_status: ImplementationStatus pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.inherited","title":"inherited: List[trestle.oscal.ssp.Inherited] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.satisfied","title":"satisfied: List[trestle.oscal.ssp.Satisfied] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.set_parameters","title":"set_parameters: List[trestle.oscal.ssp.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this by-component entry elsewhere in this or other OSCAL instances. The locally defined UUID of the by-component entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ByComponent.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization","title":" Categorization (OscalBaseModel) pydantic-model","text":"

                                                                            A set of information type identifiers qualified by the given identification system used, such as NIST SP 800-60.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Categorization(OscalBaseModel):\n\"\"\"\n    A set of information type identifiers qualified by the given identification system used, such as NIST SP 800-60.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    system: Union[AnyUrl, System] = Field(\n        ...,\n        description='Specifies the information type identification system used.',\n        title='Information Type Identification System'\n    )\n    information_type_ids: Optional[List[constr(regex=r'^\\S(.*\\S)?$')]] = Field(None, alias='information-type-ids')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.information_type_ids","title":"information_type_ids: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.system","title":"system: Union[pydantic.v1.networks.AnyUrl, trestle.oscal.ssp.System] pydantic-field required","text":"

                                                                            Specifies the information type identification system used.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Categorization.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation","title":" ControlImplementation (OscalBaseModel) pydantic-model","text":"

                                                                            Describes how the system satisfies a set of controls.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class ControlImplementation(OscalBaseModel):\n\"\"\"\n    Describes how the system satisfies a set of controls.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(\n        ...,\n        description=\n        'A statement describing important things to know about how this set of control satisfaction documentation is approached.',\n        title='Control Implementation Description'\n    )\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    implemented_requirements: List[ImplementedRequirement] = Field(..., alias='implemented-requirements')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.description","title":"description: str pydantic-field required","text":"

                                                                            A statement describing important things to know about how this set of control satisfaction documentation is approached.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.implemented_requirements","title":"implemented_requirements: List[trestle.oscal.ssp.ImplementedRequirement] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.set_parameters","title":"set_parameters: List[trestle.oscal.ssp.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ControlImplementation.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow","title":" DataFlow (OscalBaseModel) pydantic-model","text":"

                                                                            A description of the logical flow of information within the system and across its boundaries, optionally supplemented by diagrams that illustrate these flows.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class DataFlow(OscalBaseModel):\n\"\"\"\n    A description of the logical flow of information within the system and across its boundaries, optionally supplemented by diagrams that illustrate these flows.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(..., description=\"A summary of the system's data flow.\", title='Data Flow Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    diagrams: Optional[List[Diagram]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of the system's data flow.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.diagrams","title":"diagrams: List[trestle.oscal.ssp.Diagram] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DataFlow.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized","title":" DateAuthorized (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                                                            class DateAuthorized(OscalBaseModel):\n    __root__: DateDatatype = Field(\n        ..., description='The date the system received its authorization.', title='System Authorization Date'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__root__","title":"__root__: DateDatatype pydantic-field required special","text":"

                                                                            The date the system received its authorization.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateAuthorized.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype","title":" DateDatatype (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                                                            class DateDatatype(OscalBaseModel):\n    __root__: constr(\n        regex=\n        r'^(((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))(Z|(-((0[0-9]|1[0-2]):00|0[39]:30)|\\+((0[0-9]|1[0-4]):00|(0[34569]|10):30|(0[58]|12):45)))?$'\n    ) = Field(..., description='A string representing a 24-hour period with an optional timezone.')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            A string representing a 24-hour period with an optional timezone.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.DateDatatype.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram","title":" Diagram (OscalBaseModel) pydantic-model","text":"

                                                                            A graphic that provides a visual representation the system, or some aspect of it.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Diagram(OscalBaseModel):\n\"\"\"\n    A graphic that provides a visual representation the system, or some aspect of it.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this diagram elsewhere in this or other OSCAL instances. The locally defined UUID of the diagram can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Diagram ID'\n    )\n    description: Optional[str] = Field(None, description='A summary of the diagram.', title='Diagram Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    caption: Optional[str] = Field(None, description='A brief caption to annotate the diagram.', title='Caption')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.caption","title":"caption: str pydantic-field","text":"

                                                                            A brief caption to annotate the diagram.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.description","title":"description: str pydantic-field","text":"

                                                                            A summary of the diagram.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this diagram elsewhere in this or other OSCAL instances. The locally defined UUID of the diagram can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Diagram.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export","title":" Export (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies content intended for external consumption, such as with leveraged organizations.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Export(OscalBaseModel):\n\"\"\"\n    Identifies content intended for external consumption, such as with leveraged organizations.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: Optional[str] = Field(\n        None,\n        description=\n        'An implementation statement that describes the aspects of the control or control statement implementation that can be available to another system leveraging this system.',\n        title='Control Implementation Export Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    provided: Optional[List[Provided]] = Field(None)\n    responsibilities: Optional[List[Responsibility]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.description","title":"description: str pydantic-field","text":"

                                                                            An implementation statement that describes the aspects of the control or control statement implementation that can be available to another system leveraging this system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.provided","title":"provided: List[trestle.oscal.ssp.Provided] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.responsibilities","title":"responsibilities: List[trestle.oscal.ssp.Responsibility] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Export.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact","title":" Impact (OscalBaseModel) pydantic-model","text":"

                                                                            The expected level of impact resulting from the described information.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Impact(OscalBaseModel):\n\"\"\"\n    The expected level of impact resulting from the described information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    base: Base\n    selected: Optional[Selected] = None\n    adjustment_justification: Optional[AdjustmentJustification] = Field(None, alias='adjustment-justification')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.adjustment_justification","title":"adjustment_justification: AdjustmentJustification pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.base","title":"base: Base pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.selected","title":"selected: Selected pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Impact.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement","title":" ImplementedRequirement (OscalBaseModel) pydantic-model","text":"

                                                                            Describes how the system satisfies the requirements of an individual control.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class ImplementedRequirement(OscalBaseModel):\n\"\"\"\n    Describes how the system satisfies the requirements of an individual control.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control requirement elsewhere in this or other OSCAL instances. The locally defined UUID of the control requirement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Control Requirement Universally Unique Identifier',\n    )\n    control_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='control-id',\n        description=\n        'A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).',\n        title='Control Identifier Reference'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    set_parameters: Optional[List[SetParameter]] = Field(None, alias='set-parameters')\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    statements: Optional[List[Statement]] = Field(None)\n    by_components: Optional[List[ByComponent]] = Field(None, alias='by-components')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.by_components","title":"by_components: List[trestle.oscal.ssp.ByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.control_id","title":"control_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A reference to a control with a corresponding id value. When referencing an externally defined control, the Control Identifier Reference must be used in the context of the external / imported OSCAL instance (e.g., uri-reference).

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.set_parameters","title":"set_parameters: List[trestle.oscal.ssp.SetParameter] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.statements","title":"statements: List[trestle.oscal.ssp.Statement] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control requirement elsewhere in this or other OSCAL instances. The locally defined UUID of the control requirement can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImplementedRequirement.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile","title":" ImportProfile (OscalBaseModel) pydantic-model","text":"

                                                                            Used to import the OSCAL profile representing the system's control baseline.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class ImportProfile(OscalBaseModel):\n\"\"\"\n    Used to import the OSCAL profile representing the system's control baseline.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    href: str = Field(\n        ...,\n        description=\"A resolvable URL reference to the profile or catalog to use as the system's control baseline.\",\n        title='Profile Reference'\n    )\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.href","title":"href: str pydantic-field required","text":"

                                                                            A resolvable URL reference to the profile or catalog to use as the system's control baseline.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.ImportProfile.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType","title":" InformationType (OscalBaseModel) pydantic-model","text":"

                                                                            Contains details about one information type that is stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class InformationType(OscalBaseModel):\n\"\"\"\n    Contains details about one information type that is stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this information type elsewhere in this or other OSCAL instances. The locally defined UUID of the information type can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Information Type Universally Unique Identifier',\n    )\n    title: str = Field(\n        ...,\n        description=\n        'A human readable name for the information type. This title should be meaningful within the context of the system.',\n        title='title field'\n    )\n    description: str = Field(\n        ...,\n        description='A summary of how this information type is used within the system.',\n        title='Information Type Description'\n    )\n    categorizations: Optional[List[Categorization]] = Field(None)\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    confidentiality_impact: Optional[Impact] = Field(None, alias='confidentiality-impact')\n    integrity_impact: Optional[Impact] = Field(None, alias='integrity-impact')\n    availability_impact: Optional[Impact] = Field(None, alias='availability-impact')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.availability_impact","title":"availability_impact: Impact pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.categorizations","title":"categorizations: List[trestle.oscal.ssp.Categorization] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.confidentiality_impact","title":"confidentiality_impact: Impact pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of how this information type is used within the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.integrity_impact","title":"integrity_impact: Impact pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.title","title":"title: str pydantic-field required","text":"

                                                                            A human readable name for the information type. This title should be meaningful within the context of the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.uuid","title":"uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this information type elsewhere in this or other OSCAL instances. The locally defined UUID of the information type can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.InformationType.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited","title":" Inherited (OscalBaseModel) pydantic-model","text":"

                                                                            Describes a control implementation inherited by a leveraging system.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Inherited(OscalBaseModel):\n\"\"\"\n    Describes a control implementation inherited by a leveraging system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inherited entry elsewhere in this or other OSCAL instances. The locally defined UUID of the inherited control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Inherited Universally Unique Identifier',\n    )\n    provided_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='provided-uuid',\n        description=\n        'A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.',\n        title='Provided UUID'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is inheriting from a leveraged system.',\n        title='Inherited Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.description","title":"description: str pydantic-field required","text":"

                                                                            An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is inheriting from a leveraged system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.provided_uuid","title":"provided_uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this inherited entry elsewhere in this or other OSCAL instances. The locally defined UUID of the inherited control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Inherited.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization","title":" LeveragedAuthorization (OscalBaseModel) pydantic-model","text":"

                                                                            A description of another authorized system from which this system inherits capabilities that satisfy security requirements. Another term for this concept is a common control provider.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class LeveragedAuthorization(OscalBaseModel):\n\"\"\"\n    A description of another authorized system from which this system inherits capabilities that satisfy security requirements. Another term for this concept is a common control provider.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope and can be used to reference this leveraged authorization elsewhere in this or other OSCAL instances. The locally defined UUID of the leveraged authorization can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Leveraged Authorization Universally Unique Identifier',\n    )\n    title: str = Field(\n        ...,\n        description='A human readable name for the leveraged authorization in the context of the system.',\n        title='title field'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    party_uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        alias='party-uuid',\n        description='A machine-oriented identifier reference to the party that manages the leveraged system.',\n        title='party-uuid field'\n    )\n    date_authorized: DateAuthorized = Field(..., alias='date-authorized')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.date_authorized","title":"date_authorized: DateAuthorized pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.party_uuid","title":"party_uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented identifier reference to the party that manages the leveraged system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.title","title":"title: str pydantic-field required","text":"

                                                                            A human readable name for the leveraged authorization in the context of the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope and can be used to reference this leveraged authorization elsewhere in this or other OSCAL instances. The locally defined UUID of the leveraged authorization can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.LeveragedAuthorization.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model","title":" Model (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                                                            class Model(OscalBaseModel):\n    system_security_plan: SystemSecurityPlan = Field(..., alias='system-security-plan')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Model.system_security_plan","title":"system_security_plan: SystemSecurityPlan pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture","title":" NetworkArchitecture (OscalBaseModel) pydantic-model","text":"

                                                                            A description of the system's network architecture, optionally supplemented by diagrams that illustrate the network architecture.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class NetworkArchitecture(OscalBaseModel):\n\"\"\"\n    A description of the system's network architecture, optionally supplemented by diagrams that illustrate the network architecture.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    description: str = Field(\n        ..., description=\"A summary of the system's network architecture.\", title='Network Architecture Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    diagrams: Optional[List[Diagram]] = Field(None)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of the system's network architecture.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.diagrams","title":"diagrams: List[trestle.oscal.ssp.Diagram] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.NetworkArchitecture.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues","title":" OperationalStateValidValues (Enum) ","text":"Source code in trestle/oscal/ssp.py
                                                                            class OperationalStateValidValues(Enum):\n    operational = 'operational'\n    under_development = 'under-development'\n    under_major_modification = 'under-major-modification'\n    disposition = 'disposition'\n    other = 'other'\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.disposition","title":"disposition","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.operational","title":"operational","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.other","title":"other","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.under_development","title":"under_development","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.OperationalStateValidValues.under_major_modification","title":"under_major_modification","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided","title":" Provided (OscalBaseModel) pydantic-model","text":"

                                                                            Describes a capability which may be inherited by a leveraging system.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Provided(OscalBaseModel):\n\"\"\"\n    Describes a capability which may be inherited by a leveraging system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this provided entry elsewhere in this or other OSCAL instances. The locally defined UUID of the provided entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Provided Universally Unique Identifier',\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of the control or control statement implementation that can be provided to another system leveraging this system.',\n        title='Provided Control Implementation Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.description","title":"description: str pydantic-field required","text":"

                                                                            An implementation statement that describes the aspects of the control or control statement implementation that can be provided to another system leveraging this system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this provided entry elsewhere in this or other OSCAL instances. The locally defined UUID of the provided entry can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Provided.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility","title":" Responsibility (OscalBaseModel) pydantic-model","text":"

                                                                            Describes a control implementation responsibility imposed on a leveraging system.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Responsibility(OscalBaseModel):\n\"\"\"\n    Describes a control implementation responsibility imposed on a leveraging system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this responsibility elsewhere in this or other OSCAL instances. The locally defined UUID of the responsibility can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Responsibility Universally Unique Identifier',\n    )\n    provided_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='provided-uuid',\n        description=\n        'A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.',\n        title='Provided UUID'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of the control or control statement implementation that a leveraging system must implement to satisfy the control provided by a leveraged system.',\n        title='Control Implementation Responsibility Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.description","title":"description: str pydantic-field required","text":"

                                                                            An implementation statement that describes the aspects of the control or control statement implementation that a leveraging system must implement to satisfy the control provided by a leveraged system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.provided_uuid","title":"provided_uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented identifier reference to an inherited control implementation that a leveraging system is inheriting from a leveraged system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this responsibility elsewhere in this or other OSCAL instances. The locally defined UUID of the responsibility can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Responsibility.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied","title":" Satisfied (OscalBaseModel) pydantic-model","text":"

                                                                            Describes how this system satisfies a responsibility imposed by a leveraged system.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Satisfied(OscalBaseModel):\n\"\"\"\n    Describes how this system satisfies a responsibility imposed by a leveraged system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this satisfied control implementation entry elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='Satisfied Universally Unique Identifier',\n    )\n    responsibility_uuid: Optional[constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    )] = Field(\n        None,\n        alias='responsibility-uuid',\n        description=\n        'A machine-oriented identifier reference to a control implementation that satisfies a responsibility imposed by a leveraged system.',\n        title='Responsibility UUID'\n    )\n    description: str = Field(\n        ...,\n        description=\n        'An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is implementing based on a requirement from a leveraged system.',\n        title='Satisfied Control Implementation Responsibility Description'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.description","title":"description: str pydantic-field required","text":"

                                                                            An implementation statement that describes the aspects of a control or control statement implementation that a leveraging system is implementing based on a requirement from a leveraged system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.responsibility_uuid","title":"responsibility_uuid: ConstrainedStrValue pydantic-field","text":"

                                                                            A machine-oriented identifier reference to a control implementation that satisfies a responsibility imposed by a leveraged system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this satisfied control implementation entry elsewhere in this or other OSCAL instances. The locally defined UUID of the control implementation can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Satisfied.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel","title":" SecurityImpactLevel (OscalBaseModel) pydantic-model","text":"

                                                                            The overall level of expected impact resulting from unauthorized disclosure, modification, or loss of access to information.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class SecurityImpactLevel(OscalBaseModel):\n\"\"\"\n    The overall level of expected impact resulting from unauthorized disclosure, modification, or loss of access to information.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    security_objective_confidentiality: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        alias='security-objective-confidentiality',\n        description=\n        'A target-level of confidentiality for the system, based on the sensitivity of information within the system.',\n        title='Security Objective: Confidentiality'\n    )\n    security_objective_integrity: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        alias='security-objective-integrity',\n        description=\n        'A target-level of integrity for the system, based on the sensitivity of information within the system.',\n        title='Security Objective: Integrity'\n    )\n    security_objective_availability: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        alias='security-objective-availability',\n        description=\n        'A target-level of availability for the system, based on the sensitivity of information within the system.',\n        title='Security Objective: Availability'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.security_objective_availability","title":"security_objective_availability: ConstrainedStrValue pydantic-field required","text":"

                                                                            A target-level of availability for the system, based on the sensitivity of information within the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.security_objective_confidentiality","title":"security_objective_confidentiality: ConstrainedStrValue pydantic-field required","text":"

                                                                            A target-level of confidentiality for the system, based on the sensitivity of information within the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.security_objective_integrity","title":"security_objective_integrity: ConstrainedStrValue pydantic-field required","text":"

                                                                            A target-level of integrity for the system, based on the sensitivity of information within the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SecurityImpactLevel.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected","title":" Selected (OscalBaseModel) pydantic-model","text":"Source code in trestle/oscal/ssp.py
                                                                            class Selected(OscalBaseModel):\n    __root__: constr(regex=r'^\\S(.*\\S)?$') = Field(\n        ...,\n        description='The selected (Confidentiality, Integrity, or Availability) security impact level.',\n        title='Selected Level (Confidentiality, Integrity, or Availability)'\n    )\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__root__","title":"__root__: ConstrainedStrValue pydantic-field required special","text":"

                                                                            The selected (Confidentiality, Integrity, or Availability) security impact level.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Selected.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter","title":" SetParameter (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies the parameter that will be set by the enclosed value.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class SetParameter(OscalBaseModel):\n\"\"\"\n    Identifies the parameter that will be set by the enclosed value.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    param_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='param-id',\n        description=\n        \"A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.\",\n        title='Parameter ID'\n    )\n    values: List[constr(regex=r'^\\S(.*\\S)?$')] = Field(...)\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.param_id","title":"param_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented reference to a parameter within a control, who's catalog has been imported into the current implementation context.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.values","title":"values: List[pydantic.v1.types.ConstrainedStrValue] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SetParameter.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement","title":" Statement (OscalBaseModel) pydantic-model","text":"

                                                                            Identifies which statements within a control are addressed.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Statement(OscalBaseModel):\n\"\"\"\n    Identifies which statements within a control are addressed.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    statement_id: constr(\n        regex=\n        r'^[_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][_A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$'\n    ) = Field(\n        ...,\n        alias='statement-id',\n        description='A human-oriented identifier reference to a control statement.',\n        title='Control Statement Reference'\n    )\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).',\n        title='Control Statement Reference Universally Unique Identifier'\n    )\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    responsible_roles: Optional[List[common.ResponsibleRole]] = Field(None, alias='responsible-roles')\n    by_components: Optional[List[ByComponent]] = Field(None, alias='by-components')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.by_components","title":"by_components: List[trestle.oscal.ssp.ByComponent] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.responsible_roles","title":"responsible_roles: List[trestle.oscal.common.ResponsibleRole] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.statement_id","title":"statement_id: ConstrainedStrValue pydantic-field required","text":"

                                                                            A human-oriented identifier reference to a control statement.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this control statement elsewhere in this or other OSCAL instances. The UUID of the control statement in the source OSCAL instance is sufficient to reference the data item locally or globally (e.g., in an imported OSCAL instance).

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Statement.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1","title":" Status1 (OscalBaseModel) pydantic-model","text":"

                                                                            Describes the operational status of the system.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class Status1(OscalBaseModel):\n\"\"\"\n    Describes the operational status of the system.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    state: OperationalStateValidValues = Field(..., description='The current operating status.', title='State')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.state","title":"state: OperationalStateValidValues pydantic-field required","text":"

                                                                            The current operating status.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.Status1.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.System","title":" System (Enum) ","text":"

                                                                            Specifies the information type identification system used.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class System(Enum):\n\"\"\"\n    Specifies the information type identification system used.\n    \"\"\"\n\n    http___doi_org_10_6028_NIST_SP_800_60v2r1 = 'http://doi.org/10.6028/NIST.SP.800-60v2r1'\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.System.http___doi_org_10_6028_NIST_SP_800_60v2r1","title":"http___doi_org_10_6028_NIST_SP_800_60v2r1","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics","title":" SystemCharacteristics (OscalBaseModel) pydantic-model","text":"

                                                                            Contains the characteristics of the system, such as its name, purpose, and security impact level.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class SystemCharacteristics(OscalBaseModel):\n\"\"\"\n    Contains the characteristics of the system, such as its name, purpose, and security impact level.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    system_ids: List[common.SystemId] = Field(..., alias='system-ids')\n    system_name: constr(\n        regex=r'^\\S(.*\\S)?$'\n    ) = Field(..., alias='system-name', description='The full name of the system.', title='System Name - Full')\n    system_name_short: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='system-name-short',\n        description=\n        'A short name for the system, such as an acronym, that is suitable for display in a data table or summary list.',\n        title='System Name - Short'\n    )\n    description: str = Field(..., description='A summary of the system.', title='System Description')\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    date_authorized: Optional[DateAuthorized] = Field(None, alias='date-authorized')\n    security_sensitivity_level: Optional[constr(regex=r'^\\S(.*\\S)?$')] = Field(\n        None,\n        alias='security-sensitivity-level',\n        description='The overall information system sensitivity categorization, such as defined by FIPS-199.',\n        title='Security Sensitivity Level'\n    )\n    system_information: SystemInformation = Field(..., alias='system-information')\n    security_impact_level: Optional[SecurityImpactLevel] = Field(None, alias='security-impact-level')\n    status: Status1\n    authorization_boundary: AuthorizationBoundary = Field(..., alias='authorization-boundary')\n    network_architecture: Optional[NetworkArchitecture] = Field(None, alias='network-architecture')\n    data_flow: Optional[DataFlow] = Field(None, alias='data-flow')\n    responsible_parties: Optional[List[common.ResponsibleParty]] = Field(None, alias='responsible-parties')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.authorization_boundary","title":"authorization_boundary: AuthorizationBoundary pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.data_flow","title":"data_flow: DataFlow pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.date_authorized","title":"date_authorized: DateAuthorized pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.description","title":"description: str pydantic-field required","text":"

                                                                            A summary of the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.network_architecture","title":"network_architecture: NetworkArchitecture pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.responsible_parties","title":"responsible_parties: List[trestle.oscal.common.ResponsibleParty] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.security_impact_level","title":"security_impact_level: SecurityImpactLevel pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.security_sensitivity_level","title":"security_sensitivity_level: ConstrainedStrValue pydantic-field","text":"

                                                                            The overall information system sensitivity categorization, such as defined by FIPS-199.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.status","title":"status: Status1 pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_ids","title":"system_ids: List[trestle.oscal.common.SystemId] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_information","title":"system_information: SystemInformation pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_name","title":"system_name: ConstrainedStrValue pydantic-field required","text":"

                                                                            The full name of the system.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.system_name_short","title":"system_name_short: ConstrainedStrValue pydantic-field","text":"

                                                                            A short name for the system, such as an acronym, that is suitable for display in a data table or summary list.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemCharacteristics.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation","title":" SystemImplementation (OscalBaseModel) pydantic-model","text":"

                                                                            Provides information as to how the system is implemented.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class SystemImplementation(OscalBaseModel):\n\"\"\"\n    Provides information as to how the system is implemented.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    leveraged_authorizations: Optional[List[LeveragedAuthorization]] = Field(None, alias='leveraged-authorizations')\n    users: List[common.SystemUser] = Field(...)\n    components: List[common.SystemComponent] = Field(...)\n    inventory_items: Optional[List[common.InventoryItem]] = Field(None, alias='inventory-items')\n    remarks: Optional[str] = None\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.components","title":"components: List[trestle.oscal.common.SystemComponent] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.inventory_items","title":"inventory_items: List[trestle.oscal.common.InventoryItem] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.leveraged_authorizations","title":"leveraged_authorizations: List[trestle.oscal.ssp.LeveragedAuthorization] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.remarks","title":"remarks: str pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.users","title":"users: List[trestle.oscal.common.SystemUser] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemImplementation.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation","title":" SystemInformation (OscalBaseModel) pydantic-model","text":"

                                                                            Contains details about all information types that are stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class SystemInformation(OscalBaseModel):\n\"\"\"\n    Contains details about all information types that are stored, processed, or transmitted by the system, such as privacy information, and those defined in NIST SP 800-60.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    props: Optional[List[common.Property]] = Field(None)\n    links: Optional[List[common.Link]] = Field(None)\n    information_types: List[InformationType] = Field(..., alias='information-types')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.information_types","title":"information_types: List[trestle.oscal.ssp.InformationType] pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.links","title":"links: List[trestle.oscal.common.Link] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.props","title":"props: List[trestle.oscal.common.Property] pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemInformation.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan","title":" SystemSecurityPlan (OscalBaseModel) pydantic-model","text":"

                                                                            A system security plan, such as those described in NIST SP 800-18.

                                                                            Source code in trestle/oscal/ssp.py
                                                                            class SystemSecurityPlan(OscalBaseModel):\n\"\"\"\n    A system security plan, such as those described in NIST SP 800-18.\n    \"\"\"\n\n    class Config:\n        extra = Extra.forbid\n\n    uuid: constr(\n        regex=r'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$'\n    ) = Field(\n        ...,\n        description=\n        'A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this system security plan (SSP) elsewhere in this or other OSCAL instances. The locally defined UUID of the SSP can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.',\n        title='System Security Plan Universally Unique Identifier',\n    )\n    metadata: common.Metadata\n    import_profile: ImportProfile = Field(..., alias='import-profile')\n    system_characteristics: SystemCharacteristics = Field(..., alias='system-characteristics')\n    system_implementation: SystemImplementation = Field(..., alias='system-implementation')\n    control_implementation: ControlImplementation = Field(..., alias='control-implementation')\n    back_matter: Optional[common.BackMatter] = Field(None, alias='back-matter')\n
                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.back_matter","title":"back_matter: BackMatter pydantic-field","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.control_implementation","title":"control_implementation: ControlImplementation pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.import_profile","title":"import_profile: ImportProfile pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.metadata","title":"metadata: Metadata pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.system_characteristics","title":"system_characteristics: SystemCharacteristics pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.system_implementation","title":"system_implementation: SystemImplementation pydantic-field required","text":""},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.uuid","title":"uuid: ConstrainedStrValue pydantic-field required","text":"

                                                                            A machine-oriented, globally unique identifier with cross-instance scope that can be used to reference this system security plan (SSP) elsewhere in this or other OSCAL instances. The locally defined UUID of the SSP can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance).This UUID should be assigned per-subject, which means it should be consistently used to identify the same subject across revisions of the document.

                                                                            "},{"location":"api_reference/trestle.oscal.ssp/#trestle.oscal.ssp.SystemSecurityPlan.Config","title":" Config ","text":"Source code in trestle/oscal/ssp.py
                                                                            class Config:\n    extra = Extra.forbid\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/","title":"base_task","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task","title":"trestle.tasks.base_task","text":"

                                                                            Trestle tasks base templating.

                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail","title":" PassFail (TaskBase) ","text":"

                                                                            Holding pattern template for a task which does nothing and always passes.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            class PassFail(TaskBase):\n\"\"\"\n    Holding pattern template for a task which does nothing and always passes.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'pass-fail'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task pass-fail.\n\n        Attributes:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('This is a template task which reports pass fail depending on the specific configuration.')\n        logger.info(\n            'In this case if no config section is provided the task will fail. This a a task specific behavior.'\n        )\n        logger.info('Configuration flags sit under [task.pass-fail]')\n        logger.info('with two boolean flags')\n        logger.info('execute_status = True/False with a default pass')\n        logger.info('simulate_status = True/False with a default fail')\n        logger.info('Note that if the config file does not have the appropriate section this should fail.')\n        logger.info('The princple goal is a simple development example.')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        if self._config:\n            outcome = self._config.getboolean('simulate_status', fallback=True)\n            if outcome:\n                return TaskOutcome('simulated-success')\n        return TaskOutcome('simulated-failure')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide a actual outcome.\"\"\"\n        if self._config:\n            outcome = self._config.getboolean('execute_status', fallback=True)\n            if outcome:\n                return TaskOutcome('success')\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task pass-fail.

                                                                            Attributes:

                                                                            Name Type Description config_object

                                                                            Config section associated with the task.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task pass-fail.\n\n    Attributes:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.execute","title":"execute(self)","text":"

                                                                            Provide a actual outcome.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide a actual outcome.\"\"\"\n    if self._config:\n        outcome = self._config.getboolean('execute_status', fallback=True)\n        if outcome:\n            return TaskOutcome('success')\n    return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('This is a template task which reports pass fail depending on the specific configuration.')\n    logger.info(\n        'In this case if no config section is provided the task will fail. This a a task specific behavior.'\n    )\n    logger.info('Configuration flags sit under [task.pass-fail]')\n    logger.info('with two boolean flags')\n    logger.info('execute_status = True/False with a default pass')\n    logger.info('simulate_status = True/False with a default fail')\n    logger.info('Note that if the config file does not have the appropriate section this should fail.')\n    logger.info('The princple goal is a simple development example.')\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.PassFail.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    if self._config:\n        outcome = self._config.getboolean('simulate_status', fallback=True)\n        if outcome:\n            return TaskOutcome('simulated-success')\n    return TaskOutcome('simulated-failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase","title":" TaskBase (ABC) ","text":"

                                                                            Abstract base class for tasks.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            class TaskBase(ABC):\n\"\"\"\n    Abstract base class for tasks.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name: str = 'base'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"Initialize task base and store config.\"\"\"\n        self._config = config_object\n\n    @abstractmethod\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n\n    @abstractmethod\n    def execute(self) -> TaskOutcome:\n\"\"\"Execute the task including potential rollback.\"\"\"\n\n    @abstractmethod\n    def simulate(self) -> TaskOutcome:\n\"\"\"Simulate the task and report task outcome.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize task base and store config.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"Initialize task base and store config.\"\"\"\n    self._config = config_object\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.execute","title":"execute(self)","text":"

                                                                            Execute the task including potential rollback.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            @abstractmethod\ndef execute(self) -> TaskOutcome:\n\"\"\"Execute the task including potential rollback.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            @abstractmethod\ndef print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskBase.simulate","title":"simulate(self)","text":"

                                                                            Simulate the task and report task outcome.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            @abstractmethod\ndef simulate(self) -> TaskOutcome:\n\"\"\"Simulate the task and report task outcome.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome","title":" TaskOutcome (Enum) ","text":"

                                                                            Enum describing possible task outcomes.

                                                                            Source code in trestle/tasks/base_task.py
                                                                            class TaskOutcome(Enum):\n\"\"\"Enum describing possible task outcomes.\"\"\"\n\n    SUCCESS = 'success'\n    FAILURE = 'failure'\n    ROLLEDBACK = 'rolledback'\n    SIM_SUCCESS = 'simulated-success'\n    SIM_FAILURE = 'simulated-failure'\n    NOT_IMPLEMENTED = 'not-implemented'\n
                                                                            "},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.FAILURE","title":"FAILURE","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.NOT_IMPLEMENTED","title":"NOT_IMPLEMENTED","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.ROLLEDBACK","title":"ROLLEDBACK","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.SIM_FAILURE","title":"SIM_FAILURE","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.SIM_SUCCESS","title":"SIM_SUCCESS","text":""},{"location":"api_reference/trestle.tasks.base_task/#trestle.tasks.base_task.TaskOutcome.SUCCESS","title":"SUCCESS","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/","title":"cis_xlsx_to_oscal_catalog","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog","title":"trestle.tasks.cis_xlsx_to_oscal_catalog","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.timestamp","title":"timestamp","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper","title":" CatalogHelper ","text":"

                                                                            OSCAL Catalog Helper.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            class CatalogHelper:\n\"\"\"OSCAL Catalog Helper.\"\"\"\n\n    def __init__(self, title: str, version: str) -> None:\n\"\"\"Initialize.\"\"\"\n        # metadata\n        self._metadata = Metadata(title=title, last_modified=timestamp, oscal_version=OSCAL_VERSION, version=version)\n        self._root_group = OrderedDict()\n        self._root_resources = OrderedDict()\n        self._all_groups = OrderedDict()\n        self._all_controls = OrderedDict()\n\n    def add_group(self, section: str, title: str, props: List[Property], parts: List[Part]) -> None:\n\"\"\"Add group.\"\"\"\n        numdots = section.count('.')\n        if numdots == 0:\n            group = Group(title=f'{title}', id=f'CIS-{section}')\n            if props:\n                group.props = props\n            if parts:\n                group.parts = parts\n            self._root_group[section] = group\n            self._all_groups[section] = group\n        else:\n            key = '.'.join(section.split('.')[:-1])\n            parent = self._all_groups[key]\n            if parent.groups is None:\n                parent.groups = []\n            group = Group(title=f'{title}', id=f'CIS-{section}')\n            if props:\n                group.props = props\n            if parts:\n                group.parts = parts\n            parent.groups.append(group)\n            self._all_groups[section] = group\n\n    def _add_prop(self, control: Control, prop: Property) -> None:\n\"\"\"Add property to control.\"\"\"\n        control_props = control.props\n        control.props = []\n        last = 0\n        for i, control_prop in enumerate(control_props):\n            if control_prop.name == prop.name:\n                last = i\n        for i, control_prop in enumerate(control_props):\n            control.props.append(control_prop)\n            if i == last:\n                control.props.append(prop)\n\n    def add_control(\n        self,\n        section: str,\n        recommendation: str,\n        title: str,\n        props: List[Property],\n        parts: List[Part],\n        links: List[Link]\n    ) -> None:\n\"\"\"Add control.\"\"\"\n        group = self._all_groups[section]\n        if group.controls is None:\n            group.controls = []\n        id_ = f'CIS-{recommendation}'\n        if id_ in self._all_controls:\n            control = self._all_controls[id_]\n            for prop in props:\n                if prop.name == 'profile':\n                    self._add_prop(control, prop)\n        else:\n            title = f'{title}'\n            control = Control(id=id_, title=title)\n            self._all_controls[id_] = control\n            if props:\n                control.props = props\n            if parts:\n                control.parts = parts\n            if links:\n                control.links = links\n            group.controls.append(control)\n\n    def add_link(\n        self,\n        recommendation: str,\n        reference: str,\n        links: List[Link],\n    ) -> None:\n\"\"\"Add link.\"\"\"\n        id_ = f'CIS-{recommendation}'\n        if id_ not in self._root_resources:\n            res_id = str(uuid.uuid4())\n            link = Link(href=f'#{res_id}', rel='reference')\n            links.append(link)\n            resource = Resource(\n                uuid=res_id,\n                description=reference,\n            )\n            self._root_resources[id_] = resource\n\n    def get_catalog(self) -> Catalog:\n\"\"\"Get catalog.\"\"\"\n        back_matter = BackMatter(resources=list(self._root_resources.values()))\n        catalog = Catalog(\n            uuid=str(uuid.uuid4()),\n            metadata=self._metadata,\n            groups=list(self._root_group.values()),\n            back_matter=back_matter\n        )\n        return catalog\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.__init__","title":"__init__(self, title, version) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def __init__(self, title: str, version: str) -> None:\n\"\"\"Initialize.\"\"\"\n    # metadata\n    self._metadata = Metadata(title=title, last_modified=timestamp, oscal_version=OSCAL_VERSION, version=version)\n    self._root_group = OrderedDict()\n    self._root_resources = OrderedDict()\n    self._all_groups = OrderedDict()\n    self._all_controls = OrderedDict()\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.add_control","title":"add_control(self, section, recommendation, title, props, parts, links)","text":"

                                                                            Add control.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def add_control(\n    self,\n    section: str,\n    recommendation: str,\n    title: str,\n    props: List[Property],\n    parts: List[Part],\n    links: List[Link]\n) -> None:\n\"\"\"Add control.\"\"\"\n    group = self._all_groups[section]\n    if group.controls is None:\n        group.controls = []\n    id_ = f'CIS-{recommendation}'\n    if id_ in self._all_controls:\n        control = self._all_controls[id_]\n        for prop in props:\n            if prop.name == 'profile':\n                self._add_prop(control, prop)\n    else:\n        title = f'{title}'\n        control = Control(id=id_, title=title)\n        self._all_controls[id_] = control\n        if props:\n            control.props = props\n        if parts:\n            control.parts = parts\n        if links:\n            control.links = links\n        group.controls.append(control)\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.add_group","title":"add_group(self, section, title, props, parts)","text":"

                                                                            Add group.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def add_group(self, section: str, title: str, props: List[Property], parts: List[Part]) -> None:\n\"\"\"Add group.\"\"\"\n    numdots = section.count('.')\n    if numdots == 0:\n        group = Group(title=f'{title}', id=f'CIS-{section}')\n        if props:\n            group.props = props\n        if parts:\n            group.parts = parts\n        self._root_group[section] = group\n        self._all_groups[section] = group\n    else:\n        key = '.'.join(section.split('.')[:-1])\n        parent = self._all_groups[key]\n        if parent.groups is None:\n            parent.groups = []\n        group = Group(title=f'{title}', id=f'CIS-{section}')\n        if props:\n            group.props = props\n        if parts:\n            group.parts = parts\n        parent.groups.append(group)\n        self._all_groups[section] = group\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.add_link","title":"add_link(self, recommendation, reference, links)","text":"

                                                                            Add link.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def add_link(\n    self,\n    recommendation: str,\n    reference: str,\n    links: List[Link],\n) -> None:\n\"\"\"Add link.\"\"\"\n    id_ = f'CIS-{recommendation}'\n    if id_ not in self._root_resources:\n        res_id = str(uuid.uuid4())\n        link = Link(href=f'#{res_id}', rel='reference')\n        links.append(link)\n        resource = Resource(\n            uuid=res_id,\n            description=reference,\n        )\n        self._root_resources[id_] = resource\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CatalogHelper.get_catalog","title":"get_catalog(self)","text":"

                                                                            Get catalog.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def get_catalog(self) -> Catalog:\n\"\"\"Get catalog.\"\"\"\n    back_matter = BackMatter(resources=list(self._root_resources.values()))\n    catalog = Catalog(\n        uuid=str(uuid.uuid4()),\n        metadata=self._metadata,\n        groups=list(self._root_group.values()),\n        back_matter=back_matter\n    )\n    return catalog\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog","title":" CisXlsxToOscalCatalog (TaskBase) ","text":"

                                                                            Task to transform CIS .xlsx to OSCAL catalog.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            class CisXlsxToOscalCatalog(TaskBase):\n\"\"\"\n    Task to transform CIS .xlsx to OSCAL catalog.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'cis-xlsx-to-oscal-catalog'\n    ns = 'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/catalog/cis'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.cis-xlsx-to-oscal-catalog]:')\n        text1 = '  input-file             = '\n        text2 = '(required) path to read the compliance-as-code .xlsx spread sheet file.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = '(required) location to write the generated catalog.json file.'\n        logger.info(text1 + text2)\n        text1 = '  title                  = '\n        text2 = '(required) title of the CIS catalog.'\n        logger.info(text1 + text2)\n        text1 = '  version                = '\n        text2 = '(required) version of the CIS catalog.'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite       = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _get_normalized_name(self, key: str) -> str:\n\"\"\"Get normalized name.\"\"\"\n        name = key\n        name = name.replace(' ', '_')\n        name = name.replace('&', 'a')\n        name = name.replace('(', '')\n        name = name.replace(')', '')\n        return name\n\n    def _create_property(self, name: str, value: str) -> Property:\n        return Property(name=name, value=value, ns=CisXlsxToOscalCatalog.ns)\n\n    def _add_property(self, xlsx_helper: XlsxHelper, props: List[Property], row: int, key: str) -> None:\n\"\"\"Add property.\"\"\"\n        try:\n            name = self._get_normalized_name(key)\n            value = xlsx_helper.get(row, key)\n            if value:\n                props.append(self._create_property(name, value))\n        except KeyError as e:\n            text = f'key {e} not found.'\n            logger.debug(text)\n\n    def _add_property_boolean(self, xlsx_helper: XlsxHelper, props: List[Property], row: int, key: str) -> None:\n\"\"\"Add property.\"\"\"\n        try:\n            name = self._get_normalized_name(key)\n            value = xlsx_helper.get(row, key)\n            if value:\n                props.append(self._create_property(name, 'True'))\n            else:\n                props.append(self._create_property(name, 'False'))\n        except KeyError as e:\n            text = f'key {e} not found.'\n            logger.debug(text)\n\n    def _add_part(self, xlsx_helper: XlsxHelper, parts: List[Part], id_: str, row: int, key: str) -> None:\n\"\"\"Add part.\"\"\"\n        value = xlsx_helper.get(row, key)\n        if value:\n            name = self._get_normalized_name(key)\n            parts.append(Part(id=id_, name=name, prose=value))\n\n    def _add_links(\n        self, xlsx_helper: XlsxHelper, catalog_helper: CatalogHelper, links: List[Link], row: int, key: str\n    ) -> None:\n\"\"\"Add links.\"\"\"\n        value = xlsx_helper.get(row, key)\n        if value:\n            recommendation = xlsx_helper.get(row, 'recommendation #')\n            catalog_helper.add_link(recommendation, value, links)\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Wrap the execute for exception handling.\"\"\"\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        try:\n            ifile = self._config['input-file']\n            odir = self._config['output-dir']\n            title = self._config['title']\n            version = self._config['version']\n        except KeyError as e:\n            logger.info(f'key {e.args[0]} missing')\n            return TaskOutcome('failure')\n        # verbosity\n        _quiet = self._config.get('quiet', False)\n        _verbose = not _quiet\n        # output\n        overwrite = self._config.getboolean('output-overwrite', True)\n        opth = pathlib.Path(odir)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'catalog.json'\n        ofile = opth / oname\n        if not overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        xlsx_helper = XlsxHelper(ifile)\n        catalog_helper = CatalogHelper(title, version)\n        if xlsx_helper.is_ocp():\n            self._process_ocp(xlsx_helper, catalog_helper)\n        else:\n            self._process_rhel(xlsx_helper, catalog_helper)\n        catalog = catalog_helper.get_catalog()\n        # write OSCAL ComponentDefinition to file\n        if _verbose:\n            logger.info(f'output: {ofile}')\n        catalog.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _process_ocp(self, xlsx_helper: XlsxHelper, catalog_helper: CatalogHelper) -> None:\n\"\"\"Process OCP.\"\"\"\n        # transform each row into OSCAL equivalent\n        for row in xlsx_helper.row_generator():\n            section = xlsx_helper.get(row, 'section #')\n            recommendation = xlsx_helper.get(row, 'recommendation #')\n            title = xlsx_helper.get(row, 'title')\n            # init\n            props = []\n            parts = []\n            links = []\n            # props\n            self._add_property(xlsx_helper, props, row, 'profile')\n            self._add_property(xlsx_helper, props, row, 'status')\n            self._add_property(xlsx_helper, props, row, 'assessment status')\n            if recommendation is None:\n                frag = section\n            else:\n                frag = recommendation\n            # parts\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_smt', row, 'statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rat', row, 'rationale statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_imp', row, 'impact statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rem', row, 'remediation procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_aud', row, 'audit procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_inf', row, 'additional information')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_ctl', row, 'CIS Controls')\n            # group or control\n            if recommendation is None:\n                catalog_helper.add_group(section, title, props, parts)\n            else:\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG3')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG3')\n                self._add_property(xlsx_helper, props, row, 'MITRE ATT&CK Mappings')\n                self._add_links(xlsx_helper, catalog_helper, links, row, 'references')\n                catalog_helper.add_control(section, recommendation, title, props, parts, links)\n\n    def _process_rhel(self, xlsx_helper: XlsxHelper, catalog_helper: CatalogHelper) -> None:\n\"\"\"Process RHEL.\"\"\"\n        # transform each row into OSCAL equivalent\n        for row in xlsx_helper.row_generator():\n            section = xlsx_helper.get(row, 'section #')\n            recommendation = xlsx_helper.get(row, 'recommendation #')\n            title = xlsx_helper.get(row, 'title')\n            # init\n            props = []\n            parts = []\n            links = []\n            # props\n            self._add_property(xlsx_helper, props, row, 'profile')\n            self._add_property(xlsx_helper, props, row, 'assessment status')\n            if recommendation is None:\n                frag = section\n            else:\n                frag = recommendation\n            # parts\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_smt', row, 'statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rat', row, 'rational statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_imp', row, 'impact statement')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_rem', row, 'remediation procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_aud', row, 'audit procedure')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_inf', row, 'additional information')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_ctl', row, 'CIS Controls')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_1v8', row, 'CIS Safeguards 1 (v8)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_2v8', row, 'CIS Safeguards 2 (v8)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_3v8', row, 'CIS Safeguards 3 (v8)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_1v7', row, 'CIS Safeguards 1 (v7)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_2v7', row, 'CIS Safeguards 2 (v7)')\n            self._add_part(xlsx_helper, parts, f'CIS-{frag}_3v7', row, 'CIS Safeguards 3 (v7)')\n            # group or control\n            if recommendation is None:\n                catalog_helper.add_group(section, title, props, parts)\n            else:\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v7 IG3')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG1')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG2')\n                self._add_property_boolean(xlsx_helper, props, row, 'v8 IG3')\n                self._add_links(xlsx_helper, catalog_helper, links, row, 'references')\n                catalog_helper.add_control(section, recommendation, title, props, parts, links)\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.ns","title":"ns","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.cis-xlsx-to-oscal-catalog]:')\n    text1 = '  input-file             = '\n    text2 = '(required) path to read the compliance-as-code .xlsx spread sheet file.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = '(required) location to write the generated catalog.json file.'\n    logger.info(text1 + text2)\n    text1 = '  title                  = '\n    text2 = '(required) title of the CIS catalog.'\n    logger.info(text1 + text2)\n    text1 = '  version                = '\n    text2 = '(required) version of the CIS catalog.'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite       = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.CisXlsxToOscalCatalog.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper","title":" XlsxHelper ","text":"

                                                                            Xlsx Helper common functions and assistance navigating spread sheet.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            class XlsxHelper:\n\"\"\"Xlsx Helper common functions and assistance navigating spread sheet.\"\"\"\n\n    def __init__(self, file: str) -> None:\n\"\"\"Initialize.\"\"\"\n        self._spread_sheet = file\n        self._wb = load_workbook(self._spread_sheet)\n        sheet_candidates = ['Combined Profiles', 'Combined']\n        self._sheet_name = None\n        for sheet_candidate in sheet_candidates:\n            if sheet_candidate in self._wb.sheetnames:\n                self._sheet_name = sheet_candidate\n                break\n        if not self._sheet_name:\n            raise RuntimeError(f'{file} missing one of {sheet_candidates} sheet')\n        self._work_sheet = self._wb[self._sheet_name]\n        self._mapper()\n        self._key_to_col_map = {'statement': 'description'}\n\n    def is_ocp(self) -> bool:\n\"\"\"Check if sheet is for OCP.\"\"\"\n        return self._sheet_name == 'Combined Profiles'\n\n    def _normalize(self, name: str) -> str:\n\"\"\"Normalize.\"\"\"\n        return name.lower()\n\n    def _translate(self, name: str) -> str:\n\"\"\"Translate name key to column name.\"\"\"\n        return self._key_to_col_map.get(name, name)\n\n    def _mapper(self) -> None:\n\"\"\"Map columns heading names to column numbers.\"\"\"\n        self._col_name_to_number = {}\n        cols = self._work_sheet.max_column + 1\n        row = 1\n        for col in range(row, cols):\n            cell = self._work_sheet.cell(row, col)\n            if cell.value:\n                name = self._normalize(cell.value)\n                self._col_name_to_number[name] = col\n\n    def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until max reached.\"\"\"\n        row = 2\n        while row <= self._work_sheet.max_row:\n            yield row\n            row += 1\n\n    def get(self, row: int, name: str) -> str:\n\"\"\"Get cell value for given row and column name.\"\"\"\n        nname = self._normalize(name)\n        cname = self._translate(nname)\n        col = self._col_name_to_number[cname]\n        cell = self._work_sheet.cell(row, col)\n        return cell.value\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.__init__","title":"__init__(self, file) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def __init__(self, file: str) -> None:\n\"\"\"Initialize.\"\"\"\n    self._spread_sheet = file\n    self._wb = load_workbook(self._spread_sheet)\n    sheet_candidates = ['Combined Profiles', 'Combined']\n    self._sheet_name = None\n    for sheet_candidate in sheet_candidates:\n        if sheet_candidate in self._wb.sheetnames:\n            self._sheet_name = sheet_candidate\n            break\n    if not self._sheet_name:\n        raise RuntimeError(f'{file} missing one of {sheet_candidates} sheet')\n    self._work_sheet = self._wb[self._sheet_name]\n    self._mapper()\n    self._key_to_col_map = {'statement': 'description'}\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.get","title":"get(self, row, name)","text":"

                                                                            Get cell value for given row and column name.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def get(self, row: int, name: str) -> str:\n\"\"\"Get cell value for given row and column name.\"\"\"\n    nname = self._normalize(name)\n    cname = self._translate(nname)\n    col = self._col_name_to_number[cname]\n    cell = self._work_sheet.cell(row, col)\n    return cell.value\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.is_ocp","title":"is_ocp(self)","text":"

                                                                            Check if sheet is for OCP.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def is_ocp(self) -> bool:\n\"\"\"Check if sheet is for OCP.\"\"\"\n    return self._sheet_name == 'Combined Profiles'\n
                                                                            "},{"location":"api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/#trestle.tasks.cis_xlsx_to_oscal_catalog.XlsxHelper.row_generator","title":"row_generator(self)","text":"

                                                                            Generate rows until max reached.

                                                                            Source code in trestle/tasks/cis_xlsx_to_oscal_catalog.py
                                                                            def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until max reached.\"\"\"\n    row = 2\n    while row <= self._work_sheet.max_row:\n        yield row\n        row += 1\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/","title":"csv_to_oscal_cd","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd","title":"trestle.tasks.csv_to_oscal_cd","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.ADJUSTED_RISK_RATING","title":"ADJUSTED_RISK_RATING","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CHECK_DESCRIPTION","title":"CHECK_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CHECK_ID","title":"CHECK_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.COMPONENT_DESCRIPTION","title":"COMPONENT_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.COMPONENT_TITLE","title":"COMPONENT_TITLE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.COMPONENT_TYPE","title":"COMPONENT_TYPE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CONTROL_ID_LIST","title":"CONTROL_ID_LIST","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.FETCHER_DESCRIPTION","title":"FETCHER_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.FETCHER_ID","title":"FETCHER_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.HEADER_DECORATION_CHAR","title":"HEADER_DECORATION_CHAR","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.NAMESPACE","title":"NAMESPACE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.ORIGINAL_RISK_RATING","title":"ORIGINAL_RISK_RATING","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER","title":"PARAMETER","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_DESCRIPTION","title":"PARAMETER_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_ID","title":"PARAMETER_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_VALUE_ALTERNATIVES","title":"PARAMETER_VALUE_ALTERNATIVES","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PARAMETER_VALUE_DEFAULT","title":"PARAMETER_VALUE_DEFAULT","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PROFILE_DESCRIPTION","title":"PROFILE_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.PROFILE_SOURCE","title":"PROFILE_SOURCE","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.RISK_ADJUSTMENT","title":"RISK_ADJUSTMENT","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.RULE_DESCRIPTION","title":"RULE_DESCRIPTION","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.RULE_ID","title":"RULE_ID","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.Row","title":"Row","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.prefix_rule_set","title":"prefix_rule_set","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.validation","title":"validation","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn","title":" CsvColumn ","text":"

                                                                            CsvColumn.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            class CsvColumn():\n\"\"\"CsvColumn.\"\"\"\n\n    _columns_required = [\n        f'{COMPONENT_TITLE}',\n        f'{COMPONENT_DESCRIPTION}',\n        f'{COMPONENT_TYPE}',\n        f'{RULE_ID}',\n        f'{RULE_DESCRIPTION}',\n        f'{PROFILE_SOURCE}',\n        f'{PROFILE_DESCRIPTION}',\n        f'{CONTROL_ID_LIST}',\n        f'{NAMESPACE}',\n    ]\n\n    _columns_required_validation = [\n        f'{COMPONENT_TITLE}',\n        f'{COMPONENT_DESCRIPTION}',\n        f'{COMPONENT_TYPE}',\n        f'{RULE_ID}',\n        f'{NAMESPACE}',\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n    ]\n\n    _columns_optional = [\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n        f'{ORIGINAL_RISK_RATING}',\n        f'{ADJUSTED_RISK_RATING}',\n        f'{RISK_ADJUSTMENT}',\n    ]\n\n    _columns_parameter = [\n        f'{PARAMETER_ID}',\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n        f'{PARAMETER_VALUE_DEFAULT}',\n    ]\n\n    _columns_ordered = _columns_required + _columns_parameter + _columns_optional\n\n    @staticmethod\n    def get_order(column_name: str) -> int:\n\"\"\"Get order for column_name.\"\"\"\n        rval = sys.maxsize\n        if column_name in CsvColumn._columns_ordered:\n            rval = CsvColumn._columns_ordered.index(column_name)\n        return rval\n\n    @staticmethod\n    def is_column_name_required(name: str) -> bool:\n\"\"\"Is column name required.\"\"\"\n        return name in (CsvColumn._columns_required + CsvColumn._columns_required_validation)\n\n    @staticmethod\n    def is_column_name_optional(name: str) -> bool:\n\"\"\"Is column name optional.\"\"\"\n        return name in (CsvColumn._columns_optional)\n\n    @staticmethod\n    def is_column_name_parameter(name: str) -> bool:\n\"\"\"Is column name parameter.\"\"\"\n        for cname in CsvColumn._columns_parameter:\n            if name.startswith(cname):\n                return True\n        return False\n\n    @staticmethod\n    def get_required_column_names() -> List[str]:\n\"\"\"Get required column names.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_required\n        return rval\n\n    @staticmethod\n    def get_optional_column_names() -> List[str]:\n\"\"\"Get optional column names.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_optional\n        return rval\n\n    @staticmethod\n    def get_parameter_column_names() -> List[str]:\n\"\"\"Get parameter column names.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_parameters\n        return rval\n\n    @staticmethod\n    def get_required_column_names_validation() -> List[str]:\n\"\"\"Get required column names validation.\"\"\"\n        rval = []\n        rval += CsvColumn._columns_required_validation\n        return rval\n\n    _rule_property_column_names = [\n        f'{RULE_ID}',\n        f'{RULE_DESCRIPTION}',\n        f'{PARAMETER_ID}',\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n        f'{ORIGINAL_RISK_RATING}',\n        f'{ADJUSTED_RISK_RATING}',\n        f'{RISK_ADJUSTMENT}',\n    ]\n\n    @staticmethod\n    def get_rule_property_column_names() -> List[str]:\n\"\"\"Get rule property column names.\"\"\"\n        return CsvColumn._rule_property_column_names\n\n    # columns required which do not become properties\n    _columns_required_filtered = [\n        f'{COMPONENT_TITLE}',\n        f'{COMPONENT_DESCRIPTION}',\n        f'{COMPONENT_TYPE}',\n        f'{PROFILE_SOURCE}',\n        f'{PROFILE_DESCRIPTION}',\n        f'{CONTROL_ID_LIST}',\n        f'{NAMESPACE}',\n    ]\n\n    # optional columns which do not become properties, initially\n    _columns_optional_filtered = []\n\n    _columns_filtered = _columns_required_filtered + _columns_optional_filtered\n\n    @staticmethod\n    def get_filtered_required_column_names() -> List[str]:\n\"\"\"Get filtered required column names.\"\"\"\n        rval = []\n        for column_name in CsvColumn.get_required_column_names():\n            if column_name not in CsvColumn._columns_filtered:\n                rval.append(column_name)\n        return rval\n\n    @staticmethod\n    def get_filtered_optional_column_names() -> List[str]:\n\"\"\"Get filtered optional column names.\"\"\"\n        rval = []\n        for column_name in CsvColumn.get_optional_column_names():\n            if column_name not in CsvColumn._columns_filtered:\n                rval.append(column_name)\n        return rval\n\n    _check_property_column_names = [\n        f'{RULE_ID}',\n        f'{CHECK_ID}',\n        f'{CHECK_DESCRIPTION}',\n    ]\n\n    @staticmethod\n    def get_check_property_column_names() -> List[str]:\n\"\"\"Get check property column names.\"\"\"\n        return CsvColumn._check_property_column_names\n\n    # optional columns which do become properties, afterwards\n    _columns_parameters = [\n        f'{PARAMETER_ID}',\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n    ]\n\n    # optional columns which require Param_Id be present in the row\n    _columns_parameters_dependent = [\n        f'{PARAMETER_DESCRIPTION}',\n        f'{PARAMETER_VALUE_ALTERNATIVES}',\n        f'{PARAMETER_VALUE_DEFAULT}',\n    ]\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_check_property_column_names","title":"get_check_property_column_names() staticmethod","text":"

                                                                            Get check property column names.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_check_property_column_names() -> List[str]:\n\"\"\"Get check property column names.\"\"\"\n    return CsvColumn._check_property_column_names\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_filtered_optional_column_names","title":"get_filtered_optional_column_names() staticmethod","text":"

                                                                            Get filtered optional column names.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_filtered_optional_column_names() -> List[str]:\n\"\"\"Get filtered optional column names.\"\"\"\n    rval = []\n    for column_name in CsvColumn.get_optional_column_names():\n        if column_name not in CsvColumn._columns_filtered:\n            rval.append(column_name)\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_filtered_required_column_names","title":"get_filtered_required_column_names() staticmethod","text":"

                                                                            Get filtered required column names.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_filtered_required_column_names() -> List[str]:\n\"\"\"Get filtered required column names.\"\"\"\n    rval = []\n    for column_name in CsvColumn.get_required_column_names():\n        if column_name not in CsvColumn._columns_filtered:\n            rval.append(column_name)\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_optional_column_names","title":"get_optional_column_names() staticmethod","text":"

                                                                            Get optional column names.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_optional_column_names() -> List[str]:\n\"\"\"Get optional column names.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_optional\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_order","title":"get_order(column_name) staticmethod","text":"

                                                                            Get order for column_name.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_order(column_name: str) -> int:\n\"\"\"Get order for column_name.\"\"\"\n    rval = sys.maxsize\n    if column_name in CsvColumn._columns_ordered:\n        rval = CsvColumn._columns_ordered.index(column_name)\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_parameter_column_names","title":"get_parameter_column_names() staticmethod","text":"

                                                                            Get parameter column names.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_parameter_column_names() -> List[str]:\n\"\"\"Get parameter column names.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_parameters\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_required_column_names","title":"get_required_column_names() staticmethod","text":"

                                                                            Get required column names.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_required_column_names() -> List[str]:\n\"\"\"Get required column names.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_required\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_required_column_names_validation","title":"get_required_column_names_validation() staticmethod","text":"

                                                                            Get required column names validation.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_required_column_names_validation() -> List[str]:\n\"\"\"Get required column names validation.\"\"\"\n    rval = []\n    rval += CsvColumn._columns_required_validation\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.get_rule_property_column_names","title":"get_rule_property_column_names() staticmethod","text":"

                                                                            Get rule property column names.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef get_rule_property_column_names() -> List[str]:\n\"\"\"Get rule property column names.\"\"\"\n    return CsvColumn._rule_property_column_names\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.is_column_name_optional","title":"is_column_name_optional(name) staticmethod","text":"

                                                                            Is column name optional.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef is_column_name_optional(name: str) -> bool:\n\"\"\"Is column name optional.\"\"\"\n    return name in (CsvColumn._columns_optional)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.is_column_name_parameter","title":"is_column_name_parameter(name) staticmethod","text":"

                                                                            Is column name parameter.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef is_column_name_parameter(name: str) -> bool:\n\"\"\"Is column name parameter.\"\"\"\n    for cname in CsvColumn._columns_parameter:\n        if name.startswith(cname):\n            return True\n    return False\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvColumn.is_column_name_required","title":"is_column_name_required(name) staticmethod","text":"

                                                                            Is column name required.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            @staticmethod\ndef is_column_name_required(name: str) -> bool:\n\"\"\"Is column name required.\"\"\"\n    return name in (CsvColumn._columns_required + CsvColumn._columns_required_validation)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition","title":" CsvToOscalComponentDefinition (TaskBase) ","text":"

                                                                            Task to create OSCAL ComponentDefinition json.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            class CsvToOscalComponentDefinition(TaskBase):\n\"\"\"\n    Task to create OSCAL ComponentDefinition json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'csv-to-oscal-cd'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task csv-to-oscal-cd.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        name = self.name\n        oscal_name = 'component_definition'\n        #\n        logger.info(f'Help information for {name} task.')\n        logger.info('')\n        logger.info(f'Purpose: From csv produce OSCAL {oscal_name} file.')\n        logger.info('')\n        logger.info('')\n        logger.info(f'Configuration flags sit under [task.{name}]:')\n        text1 = '  title                = '\n        text2 = '(required) the component definition title.'\n        logger.info(text1 + text2)\n        text1 = '  version              = '\n        text2 = '(required) the component definition version.'\n        logger.info(text1 + text2)\n        text1 = '  csv-file             = '\n        text2 = '(required) the path of the csv file.'\n        text3 = ' [1st row are column headings; 2nd row are column descriptions; 3rd row and beyond is data]'\n        logger.info(text1 + text2 + text3)\n        text1 = '  required columns:      '\n        for text2 in CsvColumn.get_required_column_names():\n            if text2 in [f'{RULE_DESCRIPTION}', f'{PROFILE_SOURCE}', f'{PROFILE_DESCRIPTION}', f'{CONTROL_ID_LIST}']:\n                text2 += ' (see note 1)'\n            logger.info(text1 + '$$' + text2)\n            text1 = '                         '\n        text1 = '  optional columns:      '\n        for text2 in CsvColumn.get_optional_column_names():\n            if text2 in [f'{ORIGINAL_RISK_RATING}', f'{ADJUSTED_RISK_RATING}', f'{RISK_ADJUSTMENT}']:\n                text2 += ' (see note 1)'\n            else:\n                text2 += ' (see note 2)'\n            logger.info(text1 + '$' + text2)\n            text1 = '                         '\n        for text2 in CsvColumn.get_parameter_column_names():\n            text2 += ' (see notes 1, 4)'\n            logger.info(text1 + '$' + text2)\n            text1 = '                         '\n        text1 = '  comment columns:       '\n        text2 = 'Informational (see note 3)'\n        logger.info(text1 + '#' + text2)\n        text1 = '  output-dir           = '\n        text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n        logger.info(text1 + text2)\n        text1 = '  component-definition = '\n        text2 = '(optional) the path of the existing component-definition OSCAL .json file.'\n        logger.info(text1 + text2)\n        text1 = '  class.column-name    = '\n        text2 = f'(optional) the class to associate with the specified column name, e.g. class.{RULE_ID} = scc_class'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite     = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n        text1 = '  validate-controls    = '\n        text2 = '(optional) on, warn, or off [default]; validate controls exist in resolved profile.'\n        logger.info(text1 + text2)\n        # Notes\n        text1 = ''\n        text2 = ''\n        logger.info(text1 + text2)\n        text1 = 'Notes: '\n        text2 = '[1] column is ignored for validation component type'\n        logger.info(text1 + text2)\n        text1 = '       '\n        text2 = '[2] column is required for validation component type'\n        logger.info(text1 + text2)\n        text1 = '       '\n        text2 = '[3] column name starting with # causes column to be ignored'\n        logger.info(text1 + text2)\n        text1 = '       '\n        text2 = '[4] additional parameters are specified by adding a common suffix per set'\n        text3 = f', for example: {PARAMETER_ID}_1, {PARAMETER_DESCRIPTION}_1, ...{PARAMETER_ID}_2...'\n        logger.info(text1 + text2 + text3)\n\n    def configure(self) -> bool:\n\"\"\"Configure.\"\"\"\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n        # config verbosity\n        self._quiet = self._config.get('quiet', False)\n        self._verbose = not self._quiet\n        # title\n        self._title = self._config.get('title')\n        if self._title is None:\n            logger.warning('config missing \"title\"')\n            return False\n        # version\n        self._version = self._config.get('version')\n        if self._version is None:\n            logger.warning('config missing \"version\"')\n            return False\n        # config csv\n        self._csv_file = self._config.get('csv-file')\n        if self._csv_file is None:\n            logger.warning('config missing \"csv-file\"')\n            return False\n        self._csv_path = pathlib.Path(self._csv_file)\n        if not self._csv_path.exists():\n            logger.warning('\"csv-file\" not found')\n            return False\n        # announce csv\n        if self._verbose:\n            logger.info(f'input: {self._csv_file}')\n        # config cd\n        self._cd_path = None\n        self._cd_file = self._config.get('component-definition')\n        if self._cd_file is not None:\n            self._cd_path = pathlib.Path(self._cd_file)\n            if not self._cd_path.exists():\n                logger.warning('\"component-definition\" not found')\n                return False\n        # workspace\n        self._workspace = os.getcwd()\n        # validate_controls\n        self._validate_controls = self._config.get('validate-controls', 'off')\n        return True\n\n    def get_class(self, name: str) -> str:\n\"\"\"Get class value for specified name from config.\"\"\"\n        key = f'class.{name}'\n        return self._config.get(key)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.error(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Execute path core.\"\"\"\n        if not self.configure():\n            return TaskOutcome('failure')\n        # config output\n        odir = self._config.get('output-dir')\n        opth = pathlib.Path(odir)\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'component-definition.json'\n        ofile = opth / oname\n        if not self._overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # fetch existing component-definition, if any\n        self._cd_mgr = _CdMgr(self._cd_path, self._title, self._timestamp, self._version)\n        # fetch csv\n        self._csv_mgr = _CsvMgr(self._csv_path)\n        # create resolved profile -> catalog helper\n        profile_list = self._csv_mgr.get_profile_list()\n        self._resolved_profile_catalog_helper = _ResolvedProfileCatalogHelper(profile_list, self._workspace)\n        self._unresolved_controls = []\n        # calculate deletion, addition & modification rule lists\n        rules = self._calculate_rules()\n        # calculate deletion, addition & modification set-parameter lists\n        set_params = self._calculate_set_params(rules[2])\n        # calculate deletion, addition & modification control mapping lists\n        control_mappings = self._calculate_control_mappings(rules[2])\n        # rule set manager\n        self._rule_set_id_mgr = _RuleSetIdMgr(self._cd_mgr.get_max_rule_set_number(), len(rules[1]))\n        # rule additions, deletions & modifications (by row)\n        self.rules_del(rules[0])\n        self.rules_add(rules[1])\n        self.rules_mod(rules[2])\n        # set-parameters additions, deletions & modifications (by row)\n        self.set_params_del(set_params[0])\n        self.set_params_add(set_params[1])\n        self.set_params_mod(set_params[2])\n        # control mappings additions, deletions & modifications (by row)\n        self.control_mappings_del(control_mappings[0])\n        self.control_mappings_add(control_mappings[1])\n        # note: control mappings mod is currently not possible\n        # note: add/del user columns not currently supported\n        if len(self._unresolved_controls) > 0:\n            text = f'Unresolved controls: {self._unresolved_controls}'\n            if self._validate_controls == 'warn':\n                logger.warning(text)\n            elif self._validate_controls == 'on':\n                raise RuntimeError(text)\n        # prepare new/revised component definition\n        component_definition = self._cd_mgr.get_component_definition()\n        # write OSCAL ComponentDefinition to file\n        if self._verbose:\n            logger.info(f'output: {ofile}')\n        component_definition.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _calculate_rules(self) -> tuple:\n\"\"\"Calculate rules add, delete, modify.\"\"\"\n        cd_rules = self._cd_mgr.get_rule_keys()\n        csv_rules = self._csv_mgr.get_rule_keys()\n        del_rules = []\n        add_rules = []\n        mod_rules = []\n        for key in cd_rules:\n            if key in csv_rules:\n                continue\n            else:\n                del_rules.append(key)\n                logger.debug(f'rules del: {key}')\n        for key in csv_rules:\n            if key in cd_rules:\n                mod_rules.append(key)\n                logger.debug(f'rules mod: {key}')\n            else:\n                add_rules.append(key)\n                logger.debug(f'rules add: {key}')\n        return (del_rules, add_rules, mod_rules)\n\n    def _calculate_set_params(self, mod_rules: List) -> tuple:\n\"\"\"Calculate set parameters add, delete, modify.\"\"\"\n        cd_set_params = self._cd_mgr.get_set_params_keys()\n        csv_set_params = self._csv_mgr.get_set_params_keys()\n        del_set_params = []\n        add_set_params = []\n        mod_set_params = []\n        for key in cd_set_params:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in csv_set_params:\n                continue\n            else:\n                del_set_params.append(key)\n                logger.debug(f'params del: {key}')\n        for key in csv_set_params:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in cd_set_params:\n                mod_set_params.append(key)\n                logger.debug(f'params mod: {key}')\n            else:\n                add_set_params.append(key)\n                logger.debug(f'params add: {key}')\n        return (del_set_params, add_set_params, mod_set_params)\n\n    def _calculate_control_mappings(self, mod_rules: List) -> tuple:\n\"\"\"Calculate control mappings add, delete, modify.\"\"\"\n        cd_controls = self._cd_mgr.get_control_keys()\n        csv_controls = self._csv_mgr.get_control_keys()\n        del_control_mappings = []\n        add_control_mappings = []\n        mod_control_mappings = []\n        for key in cd_controls:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in csv_controls:\n                continue\n            else:\n                del_control_mappings.append(key)\n                logger.debug(f'ctl-maps del: {key}')\n        for key in csv_controls:\n            rule_key = (key[0], key[1], key[2])\n            if rule_key not in mod_rules:\n                continue\n            if key in cd_controls:\n                mod_control_mappings.append(key)\n                logger.debug(f'ctl-maps mod: {key}')\n            else:\n                add_control_mappings.append(key)\n                logger.debug(f'ctl-maps add: {key}')\n        return (del_control_mappings, add_control_mappings, mod_control_mappings)\n\n    def _get_namespace(self, rule_key: tuple) -> str:\n\"\"\"Get namespace.\"\"\"\n        return self._csv_mgr.get_value(rule_key, NAMESPACE).strip()\n\n    def _get_prop_name(self, column_name: str) -> str:\n\"\"\"Get property name.\"\"\"\n        return column_name.lstrip('$')\n\n    def rules_del(self, del_rules: List[str]) -> None:\n\"\"\"Delete rules.\"\"\"\n        for tokens in del_rules:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            description = ''\n            # component\n            component = self._cd_mgr.get_component(component_title, component_type, description)\n            # props\n            component.props = self._delete_rule_props(component, rule_id)\n\n    def _delete_rule_props(self, component: DefinedComponent, rule_id: str) -> List[Property]:\n\"\"\"Delete rule props.\"\"\"\n        props = []\n        rule_set = _RuleSetHelper.get_rule_set(component.props, rule_id)\n        for prop in component.props:\n            if prop.remarks != rule_set:\n                props.append(prop)\n            elif prop.name in self._csv_mgr.get_parameter_id_column_names():\n                self._delete_rule_set_parameter(component, prop.value)\n            elif prop.name == RULE_ID:\n                self._delete_rule_implemented_requirement(component, prop.value)\n        return props\n\n    def _control_implementation_generator(\n        self, control_implementations: List[ControlImplementation]\n    ) -> Iterator[ControlImplementation]:\n\"\"\"Control implementation generator.\"\"\"\n        if control_implementations:\n            for control_implementation in control_implementations:\n                yield control_implementation\n\n    def _set_parameter_generator(self, set_parameters: List[SetParameter]) -> Iterator[SetParameter]:\n\"\"\"Set parameter generator.\"\"\"\n        if set_parameters:\n            for set_parameter in set_parameters:\n                yield set_parameter\n\n    def _implemented_requirement_generator(\n        self, implemented_requirements: List[ImplementedRequirement]\n    ) -> Iterator[ImplementedRequirement]:\n\"\"\"Implemented-requirement generator.\"\"\"\n        if implemented_requirements:\n            for implemented_requirement in implemented_requirements:\n                yield implemented_requirement\n\n    def _delete_rule_set_parameter(self, component: DefinedComponent, parameter_id: str) -> None:\n\"\"\"Delete rule set-parameter.\"\"\"\n        control_implementations = component.control_implementations\n        for control_implementation in self._control_implementation_generator(control_implementations):\n            if control_implementation.set_parameters:\n                set_parameters = control_implementation.set_parameters\n                control_implementation.set_parameters = []\n                for set_parameter in set_parameters:\n                    if set_parameter.param_id != parameter_id:\n                        _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n                if not len(control_implementation.set_parameters):\n                    control_implementation.set_parameters = None\n\n    def _delete_rule_implemented_requirement(self, component: DefinedComponent, rule_id: str) -> None:\n\"\"\"Delete rule implemented_requirement.\"\"\"\n        control_implementations = component.control_implementations\n        component.control_implementations = []\n        for control_implementation in self._control_implementation_generator(control_implementations):\n            if control_implementation.implemented_requirements:\n                implemented_requirements = control_implementation.implemented_requirements\n                control_implementation.implemented_requirements = []\n                for implemented_requirement in implemented_requirements:\n                    self._delete_ir_props(implemented_requirement, rule_id)\n                    self._delete_ir_statements(implemented_requirement, rule_id)\n                    if len(as_list(implemented_requirement.props)) or len(as_list(implemented_requirement.statements)):\n                        control_implementation.implemented_requirements.append(implemented_requirement)\n            if len(as_list(control_implementation.implemented_requirements)):\n                component.control_implementations.append(control_implementation)\n\n    def _delete_ir_statements(self, implemented_requirement: ImplementedRequirement, rule_id: str) -> None:\n\"\"\"Delete implemented-requirement statements.\"\"\"\n        if implemented_requirement.statements:\n            statements = implemented_requirement.statements\n            implemented_requirement.statements = []\n            for statement in statements:\n                statement.props = self._delete_props(statement.props, rule_id)\n                if not len(statement.props):\n                    statement.props = None\n                if statement.props:\n                    implemented_requirement.statements.append(statement)\n            if not len(implemented_requirement.statements):\n                implemented_requirement.statements = None\n\n    def _delete_ir_props(self, implemented_requirement: ImplementedRequirement, rule_id: str) -> None:\n\"\"\"Delete implemented-requirement props.\"\"\"\n        if implemented_requirement.props:\n            implemented_requirement.props = self._delete_props(implemented_requirement.props, rule_id)\n            if not len(implemented_requirement.props):\n                implemented_requirement.props = None\n\n    def _delete_props(self, props: List[Property], rule_id: str) -> List[property]:\n\"\"\"Delete props.\"\"\"\n        rval = []\n        if props:\n            for prop in props:\n                if prop.name == RULE_ID and prop.value == rule_id:\n                    continue\n                rval.append(prop)\n        return rval\n\n    def rules_add(self, add_rules: List[str]) -> None:\n\"\"\"Add rules.\"\"\"\n        for rule_key in add_rules:\n            component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n            component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n            component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n            # component\n            component = self._cd_mgr.get_component(component_title, component_type, component_description)\n            # props\n            component.props = as_list(component.props)\n            component.props = component.props + self._create_rule_props(rule_key)\n            # additional props, when not validation component\n            if not self._is_validation(rule_key):\n                # control implementation\n                source = self._csv_mgr.get_value(rule_key, PROFILE_SOURCE)\n                description = self._csv_mgr.get_value(rule_key, PROFILE_DESCRIPTION)\n                control_implementation = self._get_control_implementation(component, source, description)\n                # set-parameters\n                set_parameters = self._create_set_parameters(rule_key)\n                if set_parameters:\n                    control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n                    _OscalHelper.add_set_parameters(control_implementation.set_parameters, set_parameters)\n                # control-mappings\n                control_mappings = self._csv_mgr.get_value(rule_key, CONTROL_ID_LIST).split()\n                self._add_rule_prop(control_implementation, control_mappings, rule_key)\n\n    def _is_validation(self, rule_key: tuple) -> bool:\n\"\"\"Check for validation component.\"\"\"\n        component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n        return component_type.lower() == validation\n\n    def _add_rule_prop(\n        self, control_implementation: ControlImplementation, control_mappings: List[str], rule_key: tuple\n    ) -> None:\n\"\"\"Add rule prop.\"\"\"\n        namespace = self._get_namespace(rule_key)\n        for control_mapping in control_mappings:\n            control_id = derive_control_id(control_mapping)\n            implemented_requirement = self._get_implemented_requirement(control_implementation, control_id)\n            # create rule implementation (as property)\n            name = RULE_ID\n            prop = Property(\n                name=name,\n                value=self._csv_mgr.get_value(rule_key, name),\n                ns=namespace,\n                class_=self.get_class(name),\n            )\n            part_id = derive_part_id(control_mapping)\n            if part_id is None:\n                implemented_requirement.props = as_list(implemented_requirement.props)\n                implemented_requirement.props.append(prop)\n            else:\n                statement = self._get_statement(implemented_requirement, part_id)\n                statement.props.append(prop)\n\n    def _create_rule_props(self, rule_key: tuple) -> List[Property]:\n\"\"\"Create rule props.\"\"\"\n        rule_set = self._rule_set_id_mgr.get_next_rule_set_id()\n        row_number = self._csv_mgr.get_row_number(rule_key)\n        rule_set_mgr = _RuleSetMgr(row_number, rule_set)\n        namespace = self._get_namespace(rule_key)\n        if self._is_validation(rule_key):\n            column_names = CsvColumn.get_check_property_column_names()\n        else:\n            column_names = CsvColumn.get_rule_property_column_names()\n        # req'd & optional props\n        for column_name in column_names:\n            prop_name = self._get_prop_name(column_name)\n            prop_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            rule_set_mgr.add_prop(prop_name, prop_value, namespace, self.get_class(prop_name))\n        if not self._is_validation(rule_key):\n            # parameter columns\n            column_names = self._csv_mgr.get_parameter_column_names()\n            for column_name in column_names:\n                prop_name = self._get_prop_name(column_name)\n                prop_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n                rule_set_mgr.add_prop(prop_name, prop_value, namespace, self.get_class(prop_name))\n        # user props\n        column_names = self._csv_mgr.get_user_column_names()\n        for column_name in column_names:\n            if column_name.startswith('#'):\n                continue\n            prop_name = self._get_prop_name(column_name)\n            prop_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            rule_set_mgr.add_prop(prop_name, prop_value, namespace, self.get_class(prop_name))\n        return rule_set_mgr.get_props()\n\n    def _get_control_implementation(\n        self, component: DefinedComponent, source: str, description: str\n    ) -> ControlImplementation:\n\"\"\"Find or create control implementation.\"\"\"\n        component.control_implementations = as_list(component.control_implementations)\n        for control_implementation in component.control_implementations:\n            if control_implementation.source == source and control_implementation.description == description:\n                return control_implementation\n        control_implementation = ControlImplementation(\n            uuid=str(uuid.uuid4()), source=source, description=description, implemented_requirements=[]\n        )\n        component.control_implementations.append(control_implementation)\n        return control_implementation\n\n    def _str_to_list(self, value: str) -> List[str]:\n\"\"\"Transform string to list.\"\"\"\n        rval = []\n        if ',' in value:\n            values = value.split(',')\n            # remove leading/trailing whitespace\n            for v in values:\n                rval.append(v.strip())\n        else:\n            rval.append(value)\n        return rval\n\n    def _create_set_parameters(self, rule_key: tuple) -> List[SetParameter]:\n\"\"\"Create set parameters.\"\"\"\n        set_parameters = []\n        for parameter_id_column_name in self._csv_mgr.get_parameter_id_column_names():\n            suffix = parameter_id_column_name.replace(PARAMETER_ID, '')\n            parameter_value_default_column_name = f'{PARAMETER_VALUE_DEFAULT}{suffix}'\n            name = self._csv_mgr.get_value(rule_key, parameter_id_column_name)\n            value = self._csv_mgr.get_value(rule_key, parameter_value_default_column_name)\n            if name and value:\n                try:\n                    values = self._str_to_list(value)\n                    set_parameter = SetParameter(\n                        param_id=name,\n                        values=values,\n                    )\n                    set_parameters.append(set_parameter)\n                except Exception:\n                    row_number = self._csv_mgr.get_row_number(rule_key)\n                    text = (\n                        f'row {row_number}: \"{name}\" is invalid for column {parameter_id_column_name} '\n                        f'and/or \"{\",\".join(values)}\" is invalid for column {parameter_value_default_column_name}'\n                    )\n                    raise RuntimeError(text)\n            elif name:\n                row_number = self._csv_mgr.get_row_number(rule_key)\n                text = f'row \"{row_number}\" missing value for \"{parameter_value_default_column_name}\"'\n                logger.debug(text)\n        return set_parameters\n\n    def _get_implemented_requirement(\n        self, control_implementation: ControlImplementation, control_id: str\n    ) -> ImplementedRequirement:\n\"\"\"Find or create implemented requirement.\"\"\"\n        if self._validate_controls != 'off':\n            if not self._resolved_profile_catalog_helper.validate(control_id):\n                if control_id not in self._unresolved_controls:\n                    self._unresolved_controls.append(control_id)\n        for implemented_requirement in control_implementation.implemented_requirements:\n            if implemented_requirement.control_id == control_id:\n                return implemented_requirement\n        implemented_requirement = ImplementedRequirement(\n            uuid=str(uuid.uuid4()),\n            control_id=control_id,\n            description='',\n        )\n        control_implementation.implemented_requirements.append(implemented_requirement)\n        return implemented_requirement\n\n    def _get_statement(self, implemented_requirement: ImplementedRequirement, part_id: str) -> Statement:\n\"\"\"Find or create statement.\"\"\"\n        implemented_requirement.statements = as_list(implemented_requirement.statements)\n        for statement in implemented_requirement.statements:\n            if statement.statement_id == part_id:\n                return statement\n        statement = Statement(\n            uuid=str(uuid.uuid4()),\n            statement_id=part_id,\n            description='',\n            props=[],\n        )\n        implemented_requirement.statements.append(statement)\n        return statement\n\n    def rules_mod(self, mod_rules: List[str]) -> None:\n\"\"\"Modify rules.\"\"\"\n        for rule_key in mod_rules:\n            component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n            component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n            component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n            # component\n            component = self._cd_mgr.get_component(component_title, component_type, component_description)\n            # props\n            component.props = self._modify_rule_props(component, rule_key)\n\n    def _modify_rule_props(self, component: DefinedComponent, rule_key: tuple) -> List[Property]:\n\"\"\"Modify rule props.\"\"\"\n        rule_id = self._csv_mgr.get_value(rule_key, RULE_ID)\n        rule_set = _RuleSetHelper.get_rule_set(component.props, rule_id)\n        rule_ns = self._csv_mgr.get_value(rule_key, NAMESPACE)\n        column_names = CsvColumn.get_filtered_required_column_names() + CsvColumn.get_filtered_optional_column_names()\n        # req'd & optional props\n        for column_name in column_names:\n            column_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            class_ = self.get_class(column_name)\n            self._cd_mgr.update_rule_definition(component, rule_set, column_name, column_value, rule_ns, class_)\n        # parameter columns\n        column_names = self._csv_mgr.get_parameter_column_names()\n        for column_name in column_names:\n            column_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            class_ = self.get_class(column_name)\n            self._cd_mgr.update_rule_definition(component, rule_set, column_name, column_value, rule_ns, class_)\n        # user props\n        column_names = self._csv_mgr.get_user_column_names()\n        for column_name in column_names:\n            column_value = self._csv_mgr.get_value(rule_key, column_name).strip()\n            self._cd_mgr.update_rule_definition(component, rule_set, column_name, column_value, rule_ns, class_)\n        return component.props\n\n    def set_params_del(self, del_set_params: List[str]) -> None:\n\"\"\"Set parameters delete.\"\"\"\n        for tokens in del_set_params:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            source = tokens[3]\n            description = tokens[4]\n            param_id = tokens[5]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            if control_implementation:\n                set_parameters = control_implementation.set_parameters\n                control_implementation.set_parameters = []\n                for set_parameter in self._set_parameter_generator(set_parameters):\n                    if set_parameter.param_id == param_id:\n                        continue\n                    _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n                if control_implementation.set_parameters == []:\n                    control_implementation.set_parameters = None\n\n    def set_params_add(self, add_set_params: List[str]) -> None:\n\"\"\"Set parameters add.\"\"\"\n        for tokens in add_set_params:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            param_id = tokens[5]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n            # add\n            rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n            values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n            set_parameter = SetParameter(\n                param_id=param_id,\n                values=values,\n            )\n            _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n\n    def set_params_mod(self, mod_set_params: List[str]) -> None:\n\"\"\"Set parameters modify.\"\"\"\n        for tokens in mod_set_params:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            param_id = tokens[5]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            if control_implementation:\n                set_parameters = control_implementation.set_parameters\n                for set_parameter in self._set_parameter_generator(set_parameters):\n                    if set_parameter.param_id != param_id:\n                        continue\n                    rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n                    values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n                    replacement = SetParameter(\n                        param_id=param_id,\n                        values=values,\n                    )\n                    if set_parameter.values == replacement.values:\n                        continue\n                    logger.debug(f'params-mod: {rule_id} {param_id} {set_parameter.values} -> {replacement.values}')\n                    set_parameter.values = replacement.values\n\n    def _control_mappings_generator(self, control_mappings: List[str]) -> Iterator[List[str]]:\n\"\"\"Control mappings generator.\"\"\"\n        for tokens in control_mappings:\n            component_title = tokens[0]\n            component_type = tokens[1]\n            source = tokens[3]\n            description = tokens[4]\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            if control_implementation:\n                yield tokens\n\n    def control_mappings_del(self, del_control_mappings: List[str]) -> None:\n\"\"\"Control mappings delete.\"\"\"\n        for tokens in self._control_mappings_generator(del_control_mappings):\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            smt_id = tokens[5]\n            control_id = derive_control_id(smt_id)\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            implemented_requirements = control_implementation.implemented_requirements\n            control_implementation.implemented_requirements = []\n            for implemented_requirement in self._implemented_requirement_generator(implemented_requirements):\n                if implemented_requirement.control_id == control_id:\n                    implemented_requirement.statements = _OscalHelper.remove_rule_statement(\n                        implemented_requirement.statements, rule_id, smt_id\n                    )\n                    implemented_requirement.props = _OscalHelper.remove_rule(implemented_requirement.props, rule_id)\n                    if len(as_list(implemented_requirement.props)) or len(as_list(implemented_requirement.statements)):\n                        control_implementation.implemented_requirements.append(implemented_requirement)\n                else:\n                    control_implementation.implemented_requirements.append(implemented_requirement)\n\n    def control_mappings_add(self, add_control_mappings: List[str]) -> None:\n\"\"\"Control mappings add.\"\"\"\n        for tokens in self._control_mappings_generator(add_control_mappings):\n            component_title = tokens[0]\n            component_type = tokens[1]\n            rule_id = tokens[2]\n            source = tokens[3]\n            description = tokens[4]\n            smt_id = tokens[5]\n            control_id = derive_control_id(smt_id)\n            control_implementation = self._cd_mgr.find_control_implementation(\n                component_title, component_type, source, description\n            )\n            implemented_requirement = self._get_implemented_requirement(control_implementation, control_id)\n            # namespace\n            rule_key = (tokens[0], tokens[1], tokens[2])\n            ns = self._get_namespace(rule_key)\n            # create rule implementation (as property)\n            name = RULE_ID\n            prop = Property(\n                name=name,\n                value=rule_id,\n                ns=ns,\n                class_=self.get_class(name),\n            )\n            if smt_id == control_id:\n                implemented_requirement.props = as_list(implemented_requirement.props)\n                implemented_requirement.props.append(prop)\n            else:\n                statement = self._get_statement(implemented_requirement, smt_id)\n                statement.props.append(prop)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task csv-to-oscal-cd.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task csv-to-oscal-cd.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.configure","title":"configure(self)","text":"

                                                                            Configure.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def configure(self) -> bool:\n\"\"\"Configure.\"\"\"\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n    # config verbosity\n    self._quiet = self._config.get('quiet', False)\n    self._verbose = not self._quiet\n    # title\n    self._title = self._config.get('title')\n    if self._title is None:\n        logger.warning('config missing \"title\"')\n        return False\n    # version\n    self._version = self._config.get('version')\n    if self._version is None:\n        logger.warning('config missing \"version\"')\n        return False\n    # config csv\n    self._csv_file = self._config.get('csv-file')\n    if self._csv_file is None:\n        logger.warning('config missing \"csv-file\"')\n        return False\n    self._csv_path = pathlib.Path(self._csv_file)\n    if not self._csv_path.exists():\n        logger.warning('\"csv-file\" not found')\n        return False\n    # announce csv\n    if self._verbose:\n        logger.info(f'input: {self._csv_file}')\n    # config cd\n    self._cd_path = None\n    self._cd_file = self._config.get('component-definition')\n    if self._cd_file is not None:\n        self._cd_path = pathlib.Path(self._cd_file)\n        if not self._cd_path.exists():\n            logger.warning('\"component-definition\" not found')\n            return False\n    # workspace\n    self._workspace = os.getcwd()\n    # validate_controls\n    self._validate_controls = self._config.get('validate-controls', 'off')\n    return True\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.control_mappings_add","title":"control_mappings_add(self, add_control_mappings)","text":"

                                                                            Control mappings add.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def control_mappings_add(self, add_control_mappings: List[str]) -> None:\n\"\"\"Control mappings add.\"\"\"\n    for tokens in self._control_mappings_generator(add_control_mappings):\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        smt_id = tokens[5]\n        control_id = derive_control_id(smt_id)\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        implemented_requirement = self._get_implemented_requirement(control_implementation, control_id)\n        # namespace\n        rule_key = (tokens[0], tokens[1], tokens[2])\n        ns = self._get_namespace(rule_key)\n        # create rule implementation (as property)\n        name = RULE_ID\n        prop = Property(\n            name=name,\n            value=rule_id,\n            ns=ns,\n            class_=self.get_class(name),\n        )\n        if smt_id == control_id:\n            implemented_requirement.props = as_list(implemented_requirement.props)\n            implemented_requirement.props.append(prop)\n        else:\n            statement = self._get_statement(implemented_requirement, smt_id)\n            statement.props.append(prop)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.control_mappings_del","title":"control_mappings_del(self, del_control_mappings)","text":"

                                                                            Control mappings delete.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def control_mappings_del(self, del_control_mappings: List[str]) -> None:\n\"\"\"Control mappings delete.\"\"\"\n    for tokens in self._control_mappings_generator(del_control_mappings):\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        smt_id = tokens[5]\n        control_id = derive_control_id(smt_id)\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        implemented_requirements = control_implementation.implemented_requirements\n        control_implementation.implemented_requirements = []\n        for implemented_requirement in self._implemented_requirement_generator(implemented_requirements):\n            if implemented_requirement.control_id == control_id:\n                implemented_requirement.statements = _OscalHelper.remove_rule_statement(\n                    implemented_requirement.statements, rule_id, smt_id\n                )\n                implemented_requirement.props = _OscalHelper.remove_rule(implemented_requirement.props, rule_id)\n                if len(as_list(implemented_requirement.props)) or len(as_list(implemented_requirement.statements)):\n                    control_implementation.implemented_requirements.append(implemented_requirement)\n            else:\n                control_implementation.implemented_requirements.append(implemented_requirement)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.execute","title":"execute(self)","text":"

                                                                            Provide an executed outcome.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.error(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.get_class","title":"get_class(self, name)","text":"

                                                                            Get class value for specified name from config.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def get_class(self, name: str) -> str:\n\"\"\"Get class value for specified name from config.\"\"\"\n    key = f'class.{name}'\n    return self._config.get(key)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    name = self.name\n    oscal_name = 'component_definition'\n    #\n    logger.info(f'Help information for {name} task.')\n    logger.info('')\n    logger.info(f'Purpose: From csv produce OSCAL {oscal_name} file.')\n    logger.info('')\n    logger.info('')\n    logger.info(f'Configuration flags sit under [task.{name}]:')\n    text1 = '  title                = '\n    text2 = '(required) the component definition title.'\n    logger.info(text1 + text2)\n    text1 = '  version              = '\n    text2 = '(required) the component definition version.'\n    logger.info(text1 + text2)\n    text1 = '  csv-file             = '\n    text2 = '(required) the path of the csv file.'\n    text3 = ' [1st row are column headings; 2nd row are column descriptions; 3rd row and beyond is data]'\n    logger.info(text1 + text2 + text3)\n    text1 = '  required columns:      '\n    for text2 in CsvColumn.get_required_column_names():\n        if text2 in [f'{RULE_DESCRIPTION}', f'{PROFILE_SOURCE}', f'{PROFILE_DESCRIPTION}', f'{CONTROL_ID_LIST}']:\n            text2 += ' (see note 1)'\n        logger.info(text1 + '$$' + text2)\n        text1 = '                         '\n    text1 = '  optional columns:      '\n    for text2 in CsvColumn.get_optional_column_names():\n        if text2 in [f'{ORIGINAL_RISK_RATING}', f'{ADJUSTED_RISK_RATING}', f'{RISK_ADJUSTMENT}']:\n            text2 += ' (see note 1)'\n        else:\n            text2 += ' (see note 2)'\n        logger.info(text1 + '$' + text2)\n        text1 = '                         '\n    for text2 in CsvColumn.get_parameter_column_names():\n        text2 += ' (see notes 1, 4)'\n        logger.info(text1 + '$' + text2)\n        text1 = '                         '\n    text1 = '  comment columns:       '\n    text2 = 'Informational (see note 3)'\n    logger.info(text1 + '#' + text2)\n    text1 = '  output-dir           = '\n    text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n    logger.info(text1 + text2)\n    text1 = '  component-definition = '\n    text2 = '(optional) the path of the existing component-definition OSCAL .json file.'\n    logger.info(text1 + text2)\n    text1 = '  class.column-name    = '\n    text2 = f'(optional) the class to associate with the specified column name, e.g. class.{RULE_ID} = scc_class'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite     = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n    text1 = '  validate-controls    = '\n    text2 = '(optional) on, warn, or off [default]; validate controls exist in resolved profile.'\n    logger.info(text1 + text2)\n    # Notes\n    text1 = ''\n    text2 = ''\n    logger.info(text1 + text2)\n    text1 = 'Notes: '\n    text2 = '[1] column is ignored for validation component type'\n    logger.info(text1 + text2)\n    text1 = '       '\n    text2 = '[2] column is required for validation component type'\n    logger.info(text1 + text2)\n    text1 = '       '\n    text2 = '[3] column name starting with # causes column to be ignored'\n    logger.info(text1 + text2)\n    text1 = '       '\n    text2 = '[4] additional parameters are specified by adding a common suffix per set'\n    text3 = f', for example: {PARAMETER_ID}_1, {PARAMETER_DESCRIPTION}_1, ...{PARAMETER_ID}_2...'\n    logger.info(text1 + text2 + text3)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.rules_add","title":"rules_add(self, add_rules)","text":"

                                                                            Add rules.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def rules_add(self, add_rules: List[str]) -> None:\n\"\"\"Add rules.\"\"\"\n    for rule_key in add_rules:\n        component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n        component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n        component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n        # component\n        component = self._cd_mgr.get_component(component_title, component_type, component_description)\n        # props\n        component.props = as_list(component.props)\n        component.props = component.props + self._create_rule_props(rule_key)\n        # additional props, when not validation component\n        if not self._is_validation(rule_key):\n            # control implementation\n            source = self._csv_mgr.get_value(rule_key, PROFILE_SOURCE)\n            description = self._csv_mgr.get_value(rule_key, PROFILE_DESCRIPTION)\n            control_implementation = self._get_control_implementation(component, source, description)\n            # set-parameters\n            set_parameters = self._create_set_parameters(rule_key)\n            if set_parameters:\n                control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n                _OscalHelper.add_set_parameters(control_implementation.set_parameters, set_parameters)\n            # control-mappings\n            control_mappings = self._csv_mgr.get_value(rule_key, CONTROL_ID_LIST).split()\n            self._add_rule_prop(control_implementation, control_mappings, rule_key)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.rules_del","title":"rules_del(self, del_rules)","text":"

                                                                            Delete rules.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def rules_del(self, del_rules: List[str]) -> None:\n\"\"\"Delete rules.\"\"\"\n    for tokens in del_rules:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        description = ''\n        # component\n        component = self._cd_mgr.get_component(component_title, component_type, description)\n        # props\n        component.props = self._delete_rule_props(component, rule_id)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.rules_mod","title":"rules_mod(self, mod_rules)","text":"

                                                                            Modify rules.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def rules_mod(self, mod_rules: List[str]) -> None:\n\"\"\"Modify rules.\"\"\"\n    for rule_key in mod_rules:\n        component_title = self._csv_mgr.get_value(rule_key, COMPONENT_TITLE)\n        component_type = self._csv_mgr.get_value(rule_key, COMPONENT_TYPE)\n        component_description = self._csv_mgr.get_value(rule_key, COMPONENT_DESCRIPTION)\n        # component\n        component = self._cd_mgr.get_component(component_title, component_type, component_description)\n        # props\n        component.props = self._modify_rule_props(component, rule_key)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.set_params_add","title":"set_params_add(self, add_set_params)","text":"

                                                                            Set parameters add.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def set_params_add(self, add_set_params: List[str]) -> None:\n\"\"\"Set parameters add.\"\"\"\n    for tokens in add_set_params:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        param_id = tokens[5]\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        control_implementation.set_parameters = as_list(control_implementation.set_parameters)\n        # add\n        rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n        values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n        set_parameter = SetParameter(\n            param_id=param_id,\n            values=values,\n        )\n        _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.set_params_del","title":"set_params_del(self, del_set_params)","text":"

                                                                            Set parameters delete.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def set_params_del(self, del_set_params: List[str]) -> None:\n\"\"\"Set parameters delete.\"\"\"\n    for tokens in del_set_params:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        source = tokens[3]\n        description = tokens[4]\n        param_id = tokens[5]\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        if control_implementation:\n            set_parameters = control_implementation.set_parameters\n            control_implementation.set_parameters = []\n            for set_parameter in self._set_parameter_generator(set_parameters):\n                if set_parameter.param_id == param_id:\n                    continue\n                _OscalHelper.add_set_parameter(control_implementation.set_parameters, set_parameter)\n            if control_implementation.set_parameters == []:\n                control_implementation.set_parameters = None\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.set_params_mod","title":"set_params_mod(self, mod_set_params)","text":"

                                                                            Set parameters modify.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def set_params_mod(self, mod_set_params: List[str]) -> None:\n\"\"\"Set parameters modify.\"\"\"\n    for tokens in mod_set_params:\n        component_title = tokens[0]\n        component_type = tokens[1]\n        rule_id = tokens[2]\n        source = tokens[3]\n        description = tokens[4]\n        param_id = tokens[5]\n        control_implementation = self._cd_mgr.find_control_implementation(\n            component_title, component_type, source, description\n        )\n        if control_implementation:\n            set_parameters = control_implementation.set_parameters\n            for set_parameter in self._set_parameter_generator(set_parameters):\n                if set_parameter.param_id != param_id:\n                    continue\n                rule_key = _CsvMgr.get_rule_key(component_title, component_type, rule_id)\n                values = [self._csv_mgr.get_default_value_by_id(rule_key, param_id)]\n                replacement = SetParameter(\n                    param_id=param_id,\n                    values=values,\n                )\n                if set_parameter.values == replacement.values:\n                    continue\n                logger.debug(f'params-mod: {rule_id} {param_id} {set_parameter.values} -> {replacement.values}')\n                set_parameter.values = replacement.values\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.CsvToOscalComponentDefinition.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd-functions","title":"Functions","text":""},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.derive_control_id","title":"derive_control_id(control_mapping)","text":"

                                                                            Derive control id.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def derive_control_id(control_mapping: str) -> str:\n\"\"\"Derive control id.\"\"\"\n    rval = control_mapping.split('_smt')[0]\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.derive_part_id","title":"derive_part_id(control_mapping)","text":"

                                                                            Derive part id.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def derive_part_id(control_mapping: str) -> str:\n\"\"\"Derive part id.\"\"\"\n    if '_smt.' in control_mapping:\n        rval = control_mapping\n    else:\n        rval = None\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.etype","title":"etype(target)","text":"

                                                                            Get etype.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def etype(target: str) -> str:\n\"\"\"Get etype.\"\"\"\n    if target:\n        return 'invalid'\n    else:\n        return 'missing'\n
                                                                            "},{"location":"api_reference/trestle.tasks.csv_to_oscal_cd/#trestle.tasks.csv_to_oscal_cd.row_property_builder","title":"row_property_builder(row, name, value, ns, class_, remarks)","text":"

                                                                            Row property builder.

                                                                            Source code in trestle/tasks/csv_to_oscal_cd.py
                                                                            def row_property_builder(row: int, name: str, value, ns: str, class_: str, remarks: str) -> Property:\n\"\"\"Row property builder.\"\"\"\n    # name\n    try:\n        Property(\n            name=name,\n            value='value',\n        )\n    except Exception:\n        text = f'property for row: {row} name: {name} is {etype(name)}'\n        raise RuntimeError(text)\n    # value\n    try:\n        Property(\n            name=name,\n            value=value,\n        )\n    except Exception:\n        text = f'property for row: {row} value: {value} is {etype(value)}'\n        raise RuntimeError(text)\n    # ns\n    try:\n        Property(\n            name=name,\n            value=value,\n            ns=ns,\n        )\n    except Exception:\n        text = f'property for row: {row} ns: {ns} is {etype(ns)}'\n        raise RuntimeError(text)\n    # class\n    try:\n        Property(\n            name=name,\n            value=value,\n            class_=class_,\n        )\n    except Exception:\n        text = f'property for row: {row} class: {class_} is {etype(class_)}'\n        raise RuntimeError(text)\n    # prop\n    prop = Property(\n        name=name,\n        value=value,\n        ns=ns,\n        class_=class_,\n        remarks=remarks,\n    )\n    return prop\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/","title":"ocp4_cis_profile_to_oscal_catalog","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog","title":"trestle.tasks.ocp4_cis_profile_to_oscal_catalog","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node","title":" Node (BaseModel) pydantic-model","text":"

                                                                            Representation of CIS profile entry.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                                                            class Node(BaseModel):\n\"\"\"Representation of CIS profile entry.\"\"\"\n\n    name: Optional[str] = Field(None)\n    description: Optional[str] = Field(None)\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.description","title":"description: str pydantic-field","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Node.name","title":"name: str pydantic-field","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog","title":" Ocp4CisProfileToOscalCatalog (TaskBase) ","text":"

                                                                            Task to transform OCP4 CIS profile to OSCAL catalog.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                                                            class Ocp4CisProfileToOscalCatalog(TaskBase):\n\"\"\"\n    Task to transform OCP4 CIS profile to OSCAL catalog.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'ocp4-cis-profile-to-oscal-catalog'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task ocp4-cis-profile-to-oscal-catalog.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-catalog]:')\n        text1 = '  input-dir              = '\n        text2 = '(required) location to read the compliance-as-code profile files.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = '(required) location to write the generated catalog.json file.'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite       = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Wrap the execute for exception handling.\"\"\"\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        try:\n            idir = self._config['input-dir']\n            odir = self._config['output-dir']\n        except KeyError as e:\n            logger.info(f'key {e.args[0]} missing')\n            return TaskOutcome('failure')\n        # verbosity\n        quiet = self._config.get('quiet', False)\n        verbose = not quiet\n        # output\n        overwrite = self._config.getboolean('output-overwrite', True)\n        opth = pathlib.Path(odir)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'catalog.json'\n        ofile = opth / oname\n        if not overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # metadata links (optional)\n        metadata_links = self._config.get('metadata-links')\n        # get list or <name>.profile files\n        filelist = self._get_filelist(idir)\n        if len(filelist) < 1:\n            logger.warning(f'input: {idir} no .profile file found')\n            return TaskOutcome('failure')\n        # initialize node list\n        self._node_map = {}\n        # process files\n        for fp in filelist:\n            lines = self._get_content(fp)\n            self._parse(lines)\n        # get root nodes\n        root_nodes = self._get_root_nodes()\n        # groups and controls\n        root = Group(title='root', groups=[])\n        for node in root_nodes:\n            group = Group(title=f'{node.name} {node.description}')\n            root.groups.append(group)\n            depth = self._depth(node.name)\n            if depth == 3:\n                self._add_groups(group, node.name, depth)\n            if depth == 2:\n                self._add_controls(group, node.name, depth)\n        # metadata\n        metadata = Metadata(\n            title=self._title, last_modified=self._timestamp, oscal_version=OSCAL_VERSION, version=trestle.__version__\n        )\n        # metadata links\n        if metadata_links is not None:\n            metadata.links = []\n            for item in metadata_links.split():\n                link = Link(href=item)\n                metadata.links.append(link)\n        # catalog\n        catalog = Catalog(uuid=_uuid(), metadata=metadata, groups=root.groups)\n        # write OSCAL ComponentDefinition to file\n        if verbose:\n            logger.info(f'output: {ofile}')\n        catalog.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _get_filelist(self, idir: str) -> List[pathlib.Path]:\n\"\"\"Get filelist.\"\"\"\n        return [x for x in pathlib.Path(idir).iterdir() if x.is_file() and x.suffix == '.profile']\n\n    def _get_content(self, fp: pathlib.Path) -> List[str]:\n\"\"\"Fetch content from file.\"\"\"\n        content = None\n        try:\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            content = f.readlines()\n            f.close()\n            return content\n        except Exception as e:\n            logger.warning(f'unable to process {fp.name}')\n            raise e\n\n    def _parse(self, lines: List[str]) -> None:\n\"\"\"Parse lines to build data structure.\"\"\"\n        for line in lines:\n            line = line.strip()\n            if line.startswith('title: ') and \"'\" in line:\n                self._title = line.split(\"'\")[1]\n                continue\n            line_parts = line.split(None, 2)\n            # must be 3 parts exactly\n            if len(line_parts) < 3:\n                continue\n            # normalized name and description\n            name = line_parts[1].rstrip('.')\n            description = line_parts[2]\n            # name must be numbers and decimal points\n            if not set(name) <= set('0123456789.'):\n                continue\n            # derive desired sortable key from name\n            key = self._get_key(name)\n            self._node_map[key] = Node(name=name, description=description)\n\n    def _get_key(self, name: str) -> Tuple[int, int, int]:\n\"\"\"Convert name to desired sortable key.\"\"\"\n        parts = name.split('.')\n        if len(parts) == 1:\n            key = (int(parts[0]), 0, 0)\n        elif len(parts) == 2:\n            key = (int(parts[0]), int(parts[1]), 0)\n        elif len(parts) == 3:\n            key = (int(parts[0]), int(parts[1]), int(parts[2]))\n        else:\n            text = f'Unexpected value: {name}'\n            raise RuntimeError(text)\n        return key\n\n    def _get_root_nodes(self) -> ValuesView[Node]:\n\"\"\"Get root nodes.\"\"\"\n        root_nodes = {}\n        for node in self._node_map.values():\n            if len(node.name) == 1:\n                root_nodes[node.name] = node\n        return root_nodes.values()\n\n    def _depth(self, prefix: str) -> int:\n\"\"\"Get maximum depth for prefix.\"\"\"\n        depth = 0\n        for node in self._node_map.values():\n            name = node.name\n            if not name.startswith(prefix):\n                continue\n            dots = name.split('.')\n            if len(dots) <= depth:\n                continue\n            depth = len(dots)\n        return depth\n\n    def _add_controls(self, group: Group, prefix: str, depth: int):\n\"\"\"Add controls to group.\"\"\"\n        controls = []\n        for key in sorted(self._node_map.keys()):\n            node = self._node_map[key]\n            name = node.name\n            if name.startswith(prefix):\n                dots = name.split('.')\n                if len(dots) == depth:\n                    id_ = f'CIS-{node.name}'\n                    title = f'{node.name} {node.description}'\n                    control = Control(id=id_, title=title)\n                    controls.append(control)\n        if len(controls) > 0:\n            group.controls = controls\n\n    def _add_groups(self, group: Group, prefix: str, depth: int):\n\"\"\"Add sub-groups to group.\"\"\"\n        groups = []\n        for key in sorted(self._node_map.keys()):\n            node = self._node_map[key]\n            name = node.name\n            if not name.startswith(prefix):\n                continue\n            if name == prefix:\n                continue\n            dots = name.split('.')\n            if len(dots) != depth - 1:\n                continue\n            title = f'{node.name} {node.description}'\n            sub_group = Group(title=title)\n            groups.append(sub_group)\n            sub_prefix = node.name\n            self._add_controls(sub_group, sub_prefix, depth)\n        if len(groups) > 0:\n            group.groups = groups\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task ocp4-cis-profile-to-oscal-catalog.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task ocp4-cis-profile-to-oscal-catalog.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create catalog from standard (e.g. CIS benchmark).')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-catalog]:')\n    text1 = '  input-dir              = '\n    text2 = '(required) location to read the compliance-as-code profile files.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = '(required) location to write the generated catalog.json file.'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite       = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/#trestle.tasks.ocp4_cis_profile_to_oscal_catalog.Ocp4CisProfileToOscalCatalog.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_catalog.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/","title":"ocp4_cis_profile_to_oscal_cd","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd","title":"trestle.tasks.ocp4_cis_profile_to_oscal_cd","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD","title":" Ocp4CisProfileToOscalCD (TaskBase) ","text":"

                                                                            Task to transform OCP4 CIS profile to OSCAL component-definition.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                                                            class Ocp4CisProfileToOscalCD(TaskBase):\n\"\"\"\n    Task to transform OCP4 CIS profile to OSCAL component-definition.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'ocp4-cis-profile-to-oscal-cd'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task ocp4-cis-profile-to-oscal-cd.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n        self._timestamp = timestamp\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create component definition from standard (e.g. CIS benchmark).')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-cd]:')\n        text1 = '  component-name         = '\n        text2 = 'component name, e.g. OSCO.'\n        logger.info(text1 + text2)\n        text1 = '  org-name               = '\n        text2 = 'organization name, e.g. International Business Machines.'\n        logger.info(text1 + text2)\n        text1 = '  org-remarks            = '\n        text2 = 'organization remarks, e.g. IBM.'\n        logger.info(text1 + text2)\n        text1 = '  folder-cac             = '\n        text2 = 'folder containing compliance-as-code artifacts, e.g adjunct-data/cis-benchmarks/content.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = 'location to write the generated component-definition.json file.'\n        logger.info(text1 + text2)\n        #\n        text1 = '  profile-name           = '\n        text2 = 'profile name, e.g. OCP4 CIS-benchmark v4.'\n        logger.info(text1 + text2)\n        text1 = '  profile-mnemonic       = '\n        text2 = 'profile mnemonic, e.g. ocp4-cis-node.'\n        logger.info(text1 + text2)\n        text1 = '  profile-ns             = '\n        text2 = 'profile ns, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud.'\n        logger.info(text1 + text2)\n        text1 = '  profile-version        = '\n        text2 = 'profile version, e.g. 1.1.'\n        logger.info(text1 + text2)\n        text1 = '  profile-check-version  = '\n        text2 = 'profile check version, e.g. 0.1.58.'\n        logger.info(text1 + text2)\n        #\n        text1 = '  profile-type           = '\n        text2 = 'profile type, e.g. OCP4.'\n        logger.info(text1 + text2)\n        text1 = '  profile-list           = '\n        text2 = 'profile list is blank separated list of \"<suffix>\" for config entries: '\n        logger.info(text1 + text2)\n        text1 = '                           profile-file.<suffix>, profile-title.<suffix>, profile-url.<suffix>'\n        text2 = ', e.g. cis cis-node.'\n        logger.info(text1 + text2)\n        text1 = '  profile-file.<suffix>  = '\n        text2 = 'path of the profile file to ingest'\n        text3 = ', e.g. ${folder-cac}/products/ocp4/profiles/cis-node.profile.'  # noqa\n        logger.info(text1 + text2 + text3)\n        text1 = '  profile-title.<suffix> = '\n        text2 = 'title of the profile'\n        text3 = ', e.g. CIS Red Hat OpenShift Container Platform 4 Benchmark.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  profile-url.<suffix>   = '\n        text2 = 'URL of the profile'\n        text3 = ', e.g. https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  rule-to-parameters-map = '\n        text2 = 'map file for set-parameters, e.g. '\n        text3 = 'adjunct-data/task-files/rule2var.json.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  selected-rules         = '\n        text2 = 'file with list of selected rules, e.g. '\n        text3 = 'adjunct-data/task-files/selected_rules.json.'\n        logger.info(text1 + text2 + text3)\n        text1 = '  enabled-rules          = '\n        text2 = 'file with list of enabled rules, e.g. '\n        text3 = 'adjunct-data/task-files/enabled_rules.json.'\n        logger.info(text1 + text2 + text3)\n        #\n        text = ''\n        logger.info(text)\n        text = 'Notes:'\n        logger.info(text)\n        text = '1. If a control has selected rules but no enabled rules, then all those selected are included.'\n        logger.info(text)\n        text = '2. If a control has selected and enabled rules, then only those enabled are included.'\n        logger.info(text)\n        text = '3. If a control has no selected rules, then none are included regardless of enabled.'\n        logger.info(text)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        try:\n            component_name = self._config['component-name']\n            org_name = self._config['org-name']\n            org_remarks = self._config['org-remarks']\n            self._folder_cac = self._config['folder-cac']\n            profile_check_version = self._config['profile-check-version']\n            profile_type = self._config['profile-type']\n            profile_mnemonic = self._config['profile-mnemonic']\n            profile_name = self._config['profile-name']\n            profile_ns = self._config['profile-ns']\n            profile_version = self._config['profile-version']\n            profile_sets = {}\n            profile_list = self._config['profile-list'].split()\n            for profile in profile_list:\n                profile_sets[profile] = {}\n                profile_sets[profile]['profile-file'] = self._config[f'profile-file.{profile}']\n                profile_sets[profile]['profile-url'] = self._config[f'profile-url.{profile}']\n                profile_sets[profile]['profile-title'] = self._config[f'profile-title.{profile}']\n                profile_sets[profile]['profile-ns'] = profile_ns\n                profile_sets[profile]['component-name'] = component_name\n            odir = self._config['output-dir']\n        except KeyError as e:\n            logger.info(f'key {e.args[0]} missing')\n            return TaskOutcome('failure')\n        # selected rules\n        self._selected_rules = self._get_filter_rules('selected-rules', 'selected')\n        # enabled rules\n        self._enabled_rules = self._get_filter_rules('enabled-rules', 'enabled')\n        # verbosity\n        quiet = self._config.get('quiet', False)\n        verbose = not quiet\n        # output\n        overwrite = self._config.getboolean('output-overwrite', True)\n        opth = pathlib.Path(odir)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'component-definition.json'\n        ofile = opth / oname\n        if not overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # fetch rule to parameters map\n        self._rule_to_parm_map = self._get_parameters_map('rule-to-parameters-map')\n        # roles, responsible_roles, parties, responsible parties\n        party_uuid_01 = str(uuid.uuid4())\n        party_uuid_02 = str(uuid.uuid4())\n        party_uuid_03 = str(uuid.uuid4())\n        roles = self._build_roles()\n        responsible_roles = self._build_responsible_roles(party_uuid_01, party_uuid_02, party_uuid_03)\n        parties = self._build_parties(org_name, org_remarks, party_uuid_01, party_uuid_02, party_uuid_03)\n        responsible_parties = self._build_responsible_parties(party_uuid_01, party_uuid_02, party_uuid_03)\n        # metadata\n        metadata = Metadata(\n            title=f'Component definition for {profile_type} profiles',\n            last_modified=self._timestamp,\n            oscal_version=OSCAL_VERSION,\n            version=trestle.__version__,\n            roles=roles,\n            parties=parties,\n            responsible_parties=responsible_parties\n        )\n        # defined component\n        component_title = component_name\n        component_description = component_name\n        defined_component = DefinedComponent(\n            uuid=str(uuid.uuid4()),\n            description=component_description,\n            title=component_title,\n            type='Service',\n        )\n        # add control implementation per profile\n        prop1 = Property(\n            name='profile_name',\n            value=profile_name,\n            class_='scc_profile_name',\n            ns=profile_ns,\n        )\n        prop2 = Property(\n            name='profile_mnemonic',\n            value=profile_mnemonic,\n            class_='scc_profile_mnemonic',\n            ns=profile_ns,\n        )\n        prop3 = Property(\n            name='profile_version',\n            value=profile_version,\n            class_='scc_profile_version',\n            ns=profile_ns,\n        )\n        prop4 = Property(\n            name='profile_check_version',\n            value=profile_check_version,\n        )\n        props = [prop1, prop2, prop3, prop4]\n        for profile in profile_list:\n            profile_set = profile_sets[profile]\n            control_implementation = self._build_control_implementation(profile_set, responsible_roles, props)\n            if control_implementation is not None:\n                if defined_component.control_implementations is None:\n                    defined_component.control_implementations = [control_implementation]\n                else:\n                    defined_component.control_implementations.append(control_implementation)\n        # defined components\n        defined_components = [defined_component]\n        # component definition\n        component_definition = ComponentDefinition(\n            uuid=str(uuid.uuid4()),\n            metadata=metadata,\n            components=defined_components,\n        )\n        # write OSCAL ComponentDefinition to file\n        if verbose:\n            logger.info(f'output: {ofile}')\n        component_definition.oscal_write(pathlib.Path(ofile))\n        return TaskOutcome('success')\n\n    def _get_set_parameter(self, rule: str) -> SetParameter:\n\"\"\"Get set parameter.\"\"\"\n        set_parameter = None\n        for key in self._rule_to_parm_map.keys():\n            logger.debug(f'{key} {rule}')\n            if key == rule:\n                value = self._rule_to_parm_map[key]\n                remarks = value['description']\n                options = value['options']\n                default_value = options['default']\n                logger.debug(f'key: {key} options: {options}')\n                set_parameter = SetParameter(\n                    param_id=rule,\n                    values=[f'{default_value}'],\n                    remarks=remarks,\n                )\n        return set_parameter\n\n    def _get_controls(self, rules: Dict[str, Tuple[str, str, str]]) -> Dict[str, List[str]]:\n\"\"\"Get controls.\"\"\"\n        controls = {}\n        for rule in rules.keys():\n            control = rules[rule][1]\n            if control not in controls.keys():\n                controls[control] = [rule]\n            else:\n                controls[control] = controls[control] + [rule]\n        # trim rules associated with control with respect to enabled rules\n        for control in controls:\n            controls[control] = self._get_trimmed_rules(control, controls[control])\n            logger.debug(f'{control} {controls[control]}')\n        return controls\n\n    # determine if trim is needed for the control, and if so then\n    # for the associated set of rules drop those that are not enabled\n    def _get_trimmed_rules(self, control: str, rules_for_control: List[str]) -> List[str]:\n\"\"\"Trim rules if any rule for control appears in enabled rules list.\"\"\"\n        retval = rules_for_control\n        if self._is_trim_needed(rules_for_control):\n            retval = []\n            for rule in rules_for_control:\n                if rule in self._enabled_rules:\n                    retval = retval + [rule]\n                    logger.debug(f'keep {control} {rule}')\n                else:\n                    logger.debug(f'drop {control} {rule}')\n        return retval\n\n    # if any rule in the set of rules for the control appears in the enabled list,\n    # then trim is needed\n    def _is_trim_needed(self, rules_for_control: List[str]) -> bool:\n\"\"\"Check if trim is needed.\"\"\"\n        retval = False\n        for rule in rules_for_control:\n            if rule in self._enabled_rules:\n                retval = True\n                break\n        return retval\n\n    # fetch the set of rules that will be included/excluded from the CIS rules\n    def _get_parameters_map(self, config_key: str) -> List[str]:\n\"\"\"Get parameters map.\"\"\"\n        try:\n            fp = pathlib.Path(self._config[config_key])\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            jdata = json.load(f)\n            parameters_map = jdata\n            f.close()\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            parameters_map = {}\n        except Exception:\n            logger.warning(f'unable to process {self._config[config_key]}')\n            parameters_map = {}\n        return parameters_map\n\n    # fetch the set of rules that will be included/excluded from the CIS rules\n    def _get_filter_rules(self, config_key: str, file_key: str) -> List[str]:\n\"\"\"Get filter rules.\"\"\"\n        try:\n            fp = pathlib.Path(self._config[config_key])\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            jdata = json.load(f)\n            try:\n                filter_rules = jdata[file_key]\n            except Exception:\n                filter_rules = jdata\n            f.close()\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            filter_rules = []\n        except Exception:\n            logger.warning(f'unable to process {self._config[config_key]}')\n            filter_rules = []\n        return filter_rules\n\n    # create map from file:\n    # key is rule\n    # value is tuple comprising [ category, control, description ]\n    def _get_cis_rules(self, filename: str) -> Dict[str, Tuple[str, str, str]]:\n\"\"\"Get CIS rules.\"\"\"\n        try:\n            fp = pathlib.Path(filename)\n            f = fp.open('r', encoding=const.FILE_ENCODING)\n            content = f.readlines()\n            rules = self._parse_cis_rules(content)\n            f.close()\n        except Exception:\n            logger.warning(f'unable to process {filename}')\n            rules = {}\n        return rules\n\n    def _parse_cis_rules(self, content: List[str]) -> Dict[str, Tuple[str, str, str]]:\n\"\"\"Parse CIS rules.\"\"\"\n        rules = {}\n        lineno = 0\n        for line in content:\n            lineno += 1\n            line = line.replace('\\n', '')\n            if line.startswith('  #### '):\n                category = line.split('  #### ')[1]\n                logger.debug(f'{lineno} category: {category}')\n            elif line.startswith('  # '):\n                text = line.split('  # ')[1].split(' ', 1)\n                if '.' in text[0]:\n                    control = text[0]\n                    desc = text[1]\n                    logger.debug(f'{lineno} control: {control} description: {desc}')\n                else:\n                    logger.debug(f'{lineno} skip: {line}')\n            elif line.startswith('    - '):\n                rule = line.split('    - ')[1]\n                logger.debug(f'{lineno} rule: {rule}')\n                if not self._is_selected(rule):\n                    logger.debug(f'not selected rule: {rule}')\n                elif rule in rules.keys():\n                    logger.info(f'duplicate rule: {rule}')\n                else:\n                    rules[rule] = [category, control, desc]\n            else:\n                logger.debug(f'{lineno} skip: {line}')\n        return rules\n\n    # rule is selected if:\n    # a) the selected rules file is not specified or is empty or\n    # b) the rule appears in the list of selected rules from the file\n    def _is_selected(self, rule: str) -> bool:\n\"\"\"Check if rule is selected.\"\"\"\n        retval = True\n        if len(self._selected_rules) > 0 and rule not in self._selected_rules:\n            retval = False\n        logger.debug(f'{retval} {rule}')\n        return retval\n\n    # rule is excluded if it does not appear in the list of trimmed rules\n    # for the control\n    def _is_excluded(self, rule: str, control: str, controls: Dict[str, List[str]]) -> bool:\n\"\"\"Check if rule is excluded.\"\"\"\n        retval = False\n        if rule not in controls[control]:\n            logger.debug(f'exclude {rule} {control}')\n            retval = True\n        return retval\n\n    def _build_roles(self) -> List[Role]:\n\"\"\"Build roles.\"\"\"\n        value = [\n            Role(id='prepared-by', title='Indicates the organization that created this content.'),\n            Role(id='prepared-for', title='Indicates the organization for which this content was created..'),\n            Role(\n                id='content-approver',\n                title='Indicates the organization responsible for all content represented in the \"document\".'\n            ),\n        ]\n        return value\n\n    def _build_control_implementation(\n        self, profile_set: Dict[str, str], responsible_roles: List[ResponsibleRole], props: List[Property]\n    ) -> ControlImplementation:\n\"\"\"Build control implementation.\"\"\"\n        implemented_requirements = self._build_implemented_requirements(profile_set, responsible_roles)\n        if len(implemented_requirements) == 0:\n            control_implementation = None\n        else:\n            control_implementation = ControlImplementation(\n                uuid=str(uuid.uuid4()),\n                source=profile_set['profile-url'],\n                description=f'{profile_set[\"component-name\"]} implemented controls for {profile_set[\"profile-title\"]}.',\n                implemented_requirements=implemented_requirements,\n                props=props,\n            )\n        return control_implementation\n\n    def _get_title(self, dir_name: str, root: str) -> str:\n\"\"\"Extract rule title from compliance-as-code rule.yml.\"\"\"\n\"\"\"\n        Operation:\n        Given is a dir_name and a root directory. We walk the\n        directory tree looking for a directory named dir_name.\n        Once found, we read the content of the rule.yml file in\n        that directory. It is likely that we read each rule.yml\n        file exactly once, since each rule appears exactly once\n        in the one or more profiles, e.g. cis-node.profile, which\n        drive the search. From the content, we find the title and\n        return its corresponding value.\n        \"\"\"\n\n        title = None\n        for path, dirs, _files in os.walk(root):\n            if dir_name in dirs:\n                folder = os.path.join(path, dir_name)\n                tpath = pathlib.Path(folder) / 'rule.yml'\n                fp = pathlib.Path(tpath)\n                f = fp.open('r', encoding=const.FILE_ENCODING)\n                content = f.readlines()\n                f.close()\n                for line in content:\n                    if line.startswith('title:'):\n                        title = line.split('title:')[1]\n                        break\n        if title is None:\n            msg = f'unable to find \"{dir_name}\"'\n            logger.warning(msg)\n            title = 'no title'\n        title = title.strip().strip(\"'\").strip('\"')\n        logger.debug(f'{title}')\n        return title\n\n    def _build_implemented_requirements(self, profile_set: Dict[str, str],\n                                        responsible_roles: List[ResponsibleRole]) -> List[ImplementedRequirement]:\n\"\"\"Build implemented requirements.\"\"\"\n        implemented_requirements = []\n        profile_file = profile_set['profile-file']\n        rules = self._get_cis_rules(profile_file)\n        controls = self._get_controls(rules)\n        rule_prefix = 'xccdf_org.ssgproject.content_rule_'\n        cac_openshift = f'{self._folder_cac}/applications/openshift'\n        for rule in rules:\n            if self._is_excluded(rule, rules[rule][1], controls):\n                continue\n            remarks = self._get_title(rule, cac_openshift)\n            prop = Property(\n                class_='scc_goal_name_id',\n                ns=profile_set['profile-ns'],\n                name='XCCDF_rule',\n                value=f'{rule_prefix}{rule}',\n                remarks=f'{remarks}'\n            )\n            props = [prop]\n            implemented_requirement = ImplementedRequirement(\n                uuid=f'{str(uuid.uuid4())}',\n                control_id=f'CIS-{rules[rule][1]}',\n                description=f'{rules[rule][2]}',\n                props=props,\n                responsible_roles=responsible_roles,\n            )\n            set_parameter = self._get_set_parameter(rule)\n            if set_parameter is not None:\n                implemented_requirement.set_parameters = [set_parameter]\n            implemented_requirements.append(implemented_requirement)\n        return implemented_requirements\n\n    def _build_responsible_roles(self, party_uuid_01: str, party_uuid_02: str,\n                                 party_uuid_03: str) -> List[ResponsibleRole]:\n\"\"\"Build responsible roles.\"\"\"\n        role_prepared_by = ResponsibleRole(role_id='prepared-by', party_uuids=[party_uuid_01])\n        role_prepared_for = ResponsibleRole(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        role_content_approver = ResponsibleRole(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            role_prepared_by,\n            role_prepared_for,\n            role_content_approver,\n        ]\n        return value\n\n    def _build_parties(\n        self, org_name: str, org_remarks: str, party_uuid_01: str, party_uuid_02: str, party_uuid_03: str\n    ) -> List[Party]:\n\"\"\"Build parties.\"\"\"\n        value = [\n            Party(uuid=party_uuid_01, type='organization', name=org_name, remarks=org_remarks),\n            Party(\n                uuid=party_uuid_02,\n                type='organization',\n                name='Customer',\n                remarks='organization to be customized at account creation only for their Component Definition'\n            ),\n            Party(\n                uuid=party_uuid_03,\n                type='organization',\n                name='ISV',\n                remarks='organization to be customized at ISV subscription only for their Component Definition'\n            ),\n        ]\n        return value\n\n    def _build_responsible_parties(self, party_uuid_01: str, party_uuid_02: str,\n                                   party_uuid_03: str) -> List[ResponsibleParty]:\n\"\"\"Build responsible parties.\"\"\"\n        prepared_by = ResponsibleParty(role_id='prepared-by', party_uuids=[party_uuid_01])\n        prepared_for = ResponsibleParty(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        content_approver = ResponsibleParty(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            prepared_by,\n            prepared_for,\n            content_approver,\n        ]\n        return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task ocp4-cis-profile-to-oscal-cd.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task ocp4-cis-profile-to-oscal-cd.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create component definition from standard (e.g. CIS benchmark).')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.ocp4-cis-profile-to-oscal-cd]:')\n    text1 = '  component-name         = '\n    text2 = 'component name, e.g. OSCO.'\n    logger.info(text1 + text2)\n    text1 = '  org-name               = '\n    text2 = 'organization name, e.g. International Business Machines.'\n    logger.info(text1 + text2)\n    text1 = '  org-remarks            = '\n    text2 = 'organization remarks, e.g. IBM.'\n    logger.info(text1 + text2)\n    text1 = '  folder-cac             = '\n    text2 = 'folder containing compliance-as-code artifacts, e.g adjunct-data/cis-benchmarks/content.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = 'location to write the generated component-definition.json file.'\n    logger.info(text1 + text2)\n    #\n    text1 = '  profile-name           = '\n    text2 = 'profile name, e.g. OCP4 CIS-benchmark v4.'\n    logger.info(text1 + text2)\n    text1 = '  profile-mnemonic       = '\n    text2 = 'profile mnemonic, e.g. ocp4-cis-node.'\n    logger.info(text1 + text2)\n    text1 = '  profile-ns             = '\n    text2 = 'profile ns, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud.'\n    logger.info(text1 + text2)\n    text1 = '  profile-version        = '\n    text2 = 'profile version, e.g. 1.1.'\n    logger.info(text1 + text2)\n    text1 = '  profile-check-version  = '\n    text2 = 'profile check version, e.g. 0.1.58.'\n    logger.info(text1 + text2)\n    #\n    text1 = '  profile-type           = '\n    text2 = 'profile type, e.g. OCP4.'\n    logger.info(text1 + text2)\n    text1 = '  profile-list           = '\n    text2 = 'profile list is blank separated list of \"<suffix>\" for config entries: '\n    logger.info(text1 + text2)\n    text1 = '                           profile-file.<suffix>, profile-title.<suffix>, profile-url.<suffix>'\n    text2 = ', e.g. cis cis-node.'\n    logger.info(text1 + text2)\n    text1 = '  profile-file.<suffix>  = '\n    text2 = 'path of the profile file to ingest'\n    text3 = ', e.g. ${folder-cac}/products/ocp4/profiles/cis-node.profile.'  # noqa\n    logger.info(text1 + text2 + text3)\n    text1 = '  profile-title.<suffix> = '\n    text2 = 'title of the profile'\n    text3 = ', e.g. CIS Red Hat OpenShift Container Platform 4 Benchmark.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  profile-url.<suffix>   = '\n    text2 = 'URL of the profile'\n    text3 = ', e.g. https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  rule-to-parameters-map = '\n    text2 = 'map file for set-parameters, e.g. '\n    text3 = 'adjunct-data/task-files/rule2var.json.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  selected-rules         = '\n    text2 = 'file with list of selected rules, e.g. '\n    text3 = 'adjunct-data/task-files/selected_rules.json.'\n    logger.info(text1 + text2 + text3)\n    text1 = '  enabled-rules          = '\n    text2 = 'file with list of enabled rules, e.g. '\n    text3 = 'adjunct-data/task-files/enabled_rules.json.'\n    logger.info(text1 + text2 + text3)\n    #\n    text = ''\n    logger.info(text)\n    text = 'Notes:'\n    logger.info(text)\n    text = '1. If a control has selected rules but no enabled rules, then all those selected are included.'\n    logger.info(text)\n    text = '2. If a control has selected and enabled rules, then only those enabled are included.'\n    logger.info(text)\n    text = '3. If a control has no selected rules, then none are included regardless of enabled.'\n    logger.info(text)\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.set_timestamp","title":"set_timestamp(self, timestamp)","text":"

                                                                            Set the timestamp.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                                                            def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n    self._timestamp = timestamp\n
                                                                            "},{"location":"api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/#trestle.tasks.ocp4_cis_profile_to_oscal_cd.Ocp4CisProfileToOscalCD.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/ocp4_cis_profile_to_oscal_cd.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/","title":"oscal_catalog_to_csv","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv","title":"trestle.tasks.oscal_catalog_to_csv","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_control","title":"level_control","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_default","title":"level_default","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_list","title":"level_list","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.level_statement","title":"level_statement","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.recurse","title":"recurse","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.timestamp","title":"timestamp","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper","title":" CatalogHelper ","text":"

                                                                            OSCAL Catalog Helper.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            class CatalogHelper:\n\"\"\"OSCAL Catalog Helper.\"\"\"\n\n    def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n        self.path = path\n        self.catalog = Catalog.oscal_read(path)\n        self.catalog_interface = CatalogInterface(self.catalog)\n        self._init_control_parent_map()\n\n    def _init_control_parent_map(self, recurse=True) -> None:\n\"\"\"Initialize map: Child Control.id to parent Control.\"\"\"\n        self._control_parent_map = {}\n        for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n            parents = self.catalog_interface.get_dependent_control_ids(control.id)\n            for parent in parents:\n                # assert child has only one parent\n                if parent in self._control_parent_map.keys():\n                    raise RuntimeError('{parent} duplicate?')\n                self._control_parent_map[parent] = control\n\n    def get_parent_control(self, ctl_id: str) -> Control:\n\"\"\"Return parent Control of child Control.id, if any.\"\"\"\n        return self._control_parent_map.get(ctl_id)\n\n    def get_family_controls(self, ctl_id: str) -> List[Control]:\n\"\"\"Return family of controls for Control.id, if any.\"\"\"\n        rval = []\n        search_id = ctl_id.split('.')[0]\n        for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n            if control.id.startswith(search_id):\n                rval.append(control)\n        return rval\n\n    def get_controls(self, recurse=True) -> Iterator:\n\"\"\"Return controls iterator.\"\"\"\n        for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n            yield control\n\n    def get_statement_text_for_control(self, control: Control) -> Optional[str]:\n\"\"\"Get statement text for control.\"\"\"\n        statement_text = self._withdrawn(control)\n        return statement_text\n\n    def get_statement_text_for_part(self, control: Control, part: Part) -> Optional[str]:\n\"\"\"Get statement text for part.\"\"\"\n        statement_text = self._derive_text(control, part)\n        if part.parts:\n            for subpart in part.parts:\n                if '_smt' in subpart.id:\n                    partial_text = self._derive_text(control, subpart)\n                    statement_text = join_str(statement_text, partial_text)\n        return statement_text\n\n    def _withdrawn(self, control: Control) -> Optional[str]:\n\"\"\"Check if withdrawn.\"\"\"\n        rval = None\n        for prop in control.props:\n            if prop.name.lower() == 'status' and prop.value.lower() == 'withdrawn':\n                status = self._get_status(control)\n                rval = join_str('Withdrawn', status, '')\n                rval = f'[{rval}]'\n                break\n        return rval\n\n    def _link_generator(self, control: Control) -> Iterator[Link]:\n\"\"\"Link generator.\"\"\"\n        if control.links:\n            for link in control.links:\n                yield link\n\n    def _get_status(self, control: Control) -> Optional[str]:\n\"\"\"Get status.\"\"\"\n        rval = None\n        ilist = None\n        for link in self._link_generator(control):\n            if link.rel.lower() == 'moved-to':\n                moved = self._href_to_control(link.href)\n                rval = f': Moved to {moved}.'\n                break\n            if link.rel.lower() == 'incorporated-into':\n                incorporated = self._href_to_control(link.href)\n                if ilist is None:\n                    ilist = f'{incorporated}'\n                else:\n                    ilist = f'{ilist}, {incorporated}'\n        if ilist:\n            rval = f': Incorporated into {ilist}.'\n        return rval\n\n    def _href_to_control(self, href: str) -> str:\n\"\"\"Convert href to control.\"\"\"\n        rval = href.replace('#', '').upper()\n        return rval\n\n    def _derive_text(self, control: Control, part: Part) -> Optional[str]:\n\"\"\"Derive control text.\"\"\"\n        rval = None\n        if part.prose:\n            id_ = self._derive_id(part.id)\n            text = self._resolve_parms(control, part.prose)\n            rval = join_str(id_, text)\n        return rval\n\n    def _derive_id(self, id_: str) -> str:\n\"\"\"Derive control text sub-part id.\"\"\"\n        rval = None\n        id_parts = id_.split('_smt')\n        if id_parts[1]:\n            id_sub_parts = id_parts[1].split('.')\n            if len(id_sub_parts) == 2:\n                rval = f'{id_sub_parts[1]}.'\n            elif len(id_sub_parts) == 3:\n                rval = f'{id_sub_parts[2]}.'\n            elif len(id_sub_parts) == 4:\n                rval = f'({id_sub_parts[3]})'\n        return rval\n\n    def _resolve_parms(self, control: Control, utext: str) -> str:\n\"\"\"Resolve parm.\"\"\"\n        rtext = self._resolve_parms_for_control(control, utext)\n        if '{{' in rtext:\n            parent_control = self.get_parent_control(control.id)\n            if parent_control:\n                rtext = self._resolve_parms_for_control(parent_control, rtext)\n        if '{{' in rtext:\n            family_controls = self.get_family_controls(control.id)\n            for family_control in family_controls:\n                rtext = self._resolve_parms_for_control(family_control, rtext)\n        if '{{' in rtext:\n            text = f'control.id: {control.id} unresolved: {rtext}'\n            raise RuntimeError(text)\n        return rtext\n\n    def _resolve_parms_for_control(self, control: Control, utext: str) -> str:\n\"\"\"Resolve parms for control.\"\"\"\n        rtext = utext\n        staches: List[str] = re.findall(r'{{.*?}}', utext)\n        if staches:\n            for stach in staches:\n                parm_id = stach\n                parm_id = parm_id.replace('{{', '')\n                parm_id = parm_id.replace('}}', '')\n                parm_id = parm_id.split(',')[1].strip()\n                value = self._get_parm_value(control, parm_id)\n                if value:\n                    rtext = rtext.replace(stach, value)\n        return rtext\n\n    def _get_parm_value(self, control: Control, parm_id: str) -> str:\n\"\"\"Get parm value.\"\"\"\n        rval = None\n        if control.params:\n            for param in control.params:\n                if param.id != parm_id:\n                    continue\n                if param.label:\n                    rval = f'[Assignment: {param.label}]'\n                elif param.select:\n                    choices = self._get_parm_choices(control, param)\n                    if param.select.how_many == HowMany.one:\n                        rval = f'[Selection (one): {choices}]'\n                    else:\n                        rval = f'[Selection (one or more): {choices}]'\n                    break\n        return rval\n\n    def _get_parm_choices(self, control: Control, param: Parameter) -> str:\n\"\"\"Get parm choices.\"\"\"\n        choices = ''\n        for choice in param.select.choice:\n            rchoice = self._resolve_parms(control, choice)\n            if choices:\n                choices += f'; {rchoice}'\n            else:\n                choices += f'{rchoice}'\n        return choices\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.__init__","title":"__init__(self, path) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n    self.path = path\n    self.catalog = Catalog.oscal_read(path)\n    self.catalog_interface = CatalogInterface(self.catalog)\n    self._init_control_parent_map()\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_controls","title":"get_controls(self, recurse=True)","text":"

                                                                            Return controls iterator.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def get_controls(self, recurse=True) -> Iterator:\n\"\"\"Return controls iterator.\"\"\"\n    for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n        yield control\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_family_controls","title":"get_family_controls(self, ctl_id)","text":"

                                                                            Return family of controls for Control.id, if any.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def get_family_controls(self, ctl_id: str) -> List[Control]:\n\"\"\"Return family of controls for Control.id, if any.\"\"\"\n    rval = []\n    search_id = ctl_id.split('.')[0]\n    for control in self.catalog_interface.get_all_controls_from_catalog(recurse):\n        if control.id.startswith(search_id):\n            rval.append(control)\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_parent_control","title":"get_parent_control(self, ctl_id)","text":"

                                                                            Return parent Control of child Control.id, if any.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def get_parent_control(self, ctl_id: str) -> Control:\n\"\"\"Return parent Control of child Control.id, if any.\"\"\"\n    return self._control_parent_map.get(ctl_id)\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_statement_text_for_control","title":"get_statement_text_for_control(self, control)","text":"

                                                                            Get statement text for control.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def get_statement_text_for_control(self, control: Control) -> Optional[str]:\n\"\"\"Get statement text for control.\"\"\"\n    statement_text = self._withdrawn(control)\n    return statement_text\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CatalogHelper.get_statement_text_for_part","title":"get_statement_text_for_part(self, control, part)","text":"

                                                                            Get statement text for part.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def get_statement_text_for_part(self, control: Control, part: Part) -> Optional[str]:\n\"\"\"Get statement text for part.\"\"\"\n    statement_text = self._derive_text(control, part)\n    if part.parts:\n        for subpart in part.parts:\n            if '_smt' in subpart.id:\n                partial_text = self._derive_text(control, subpart)\n                statement_text = join_str(statement_text, partial_text)\n    return statement_text\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager","title":" ContentManager ","text":"

                                                                            Content manager.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            class ContentManager():\n\"\"\"Content manager.\"\"\"\n\n    def __init__(self, catalog_helper: CatalogHelper) -> None:\n\"\"\"Initialize.\"\"\"\n        self.catalog_helper = catalog_helper\n        self.rows = []\n        self.row_template = None\n\n    def add(self, row: List):\n\"\"\"Add row.\"\"\"\n        n_row = copy.copy(row)\n        t_row = self.row_template\n        if t_row:\n            for index in range(3):\n                if n_row[index] == t_row[index]:\n                    n_row[index] = None\n        self.rows.append(n_row)\n        self.row_template = row\n\n    def get_content(self, level: str) -> List:\n\"\"\"Get content.\"\"\"\n        if level == level_control:\n            rval = self._get_content_by_control()\n        else:\n            rval = self._get_content_by_statement()\n        return rval\n\n    def _get_content_by_statement(self) -> List:\n\"\"\"Get content by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        header = ['Control Identifier', 'Control Title', 'Statement Identifier', 'Statement Text']\n        self.rows.append(header)\n        for control in catalog_helper.get_controls():\n            control_id = convert_control_id(control.id)\n            if control.parts:\n                self._add_parts_by_statement(control)\n            else:\n                statement_text = catalog_helper.get_statement_text_for_control(control)\n                row = [control_id, control.title, '', statement_text]\n                self.add(row)\n        return self.rows\n\n    def _add_subparts_by_statement(self, control: Control, part: Part) -> None:\n\"\"\"Add subparts by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        control_id = convert_control_id(control.id)\n        for subpart in part.parts:\n            if '_smt' in subpart.id:\n                statement_text = catalog_helper.get_statement_text_for_part(control, subpart)\n                row = [control_id, control.title, convert_smt_id(subpart.id), statement_text]\n                self.add(row)\n\n    def _add_parts_by_statement(self, control: Control) -> None:\n\"\"\"Add parts by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        control_id = convert_control_id(control.id)\n        for part in control.parts:\n            if part.id:\n                if '_smt' not in part.id:\n                    continue\n                if part.parts:\n                    self._add_subparts_by_statement(control, part)\n                else:\n                    statement_text = catalog_helper.get_statement_text_for_part(control, part)\n                    row = [control_id, control.title, convert_smt_id(part.id), statement_text]\n                    self.add(row)\n\n    def _get_content_by_control(self) -> List:\n\"\"\"Get content by statement.\"\"\"\n        catalog_helper = self.catalog_helper\n        header = ['Control Identifier', 'Control Title', 'Control Text']\n        self.rows.append(header)\n        for control in catalog_helper.get_controls():\n            control_id = convert_control_id(control.id)\n            if control.parts:\n                self._add_parts_by_control(control)\n            else:\n                control_text = catalog_helper.get_statement_text_for_control(control)\n                row = [control_id, control.title, control_text]\n                self.add(row)\n        return self.rows\n\n    def _add_subparts_by_control(self, control: Control, part: Part, control_text) -> str:\n\"\"\"Add subparts by control.\"\"\"\n        catalog_helper = self.catalog_helper\n        for subpart in part.parts:\n            if '_smt' in subpart.id:\n                statement_text = catalog_helper.get_statement_text_for_part(control, subpart)\n                control_text = join_str(control_text, statement_text)\n        return control_text\n\n    def _add_parts_by_control(self, control: Control) -> None:\n\"\"\"Add parts by control.\"\"\"\n        catalog_helper = self.catalog_helper\n        control_id = convert_control_id(control.id)\n        control_text = None\n        for part in control.parts:\n            if part.id:\n                if '_smt' not in part.id:\n                    continue\n                if part.parts:\n                    control_text = self._add_subparts_by_control(control, part, control_text)\n                else:\n                    statement_text = catalog_helper.get_statement_text_for_part(control, part)\n                    control_text = join_str(control_text, statement_text)\n        row = [control_id, control.title, control_text]\n        self.add(row)\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager.__init__","title":"__init__(self, catalog_helper) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def __init__(self, catalog_helper: CatalogHelper) -> None:\n\"\"\"Initialize.\"\"\"\n    self.catalog_helper = catalog_helper\n    self.rows = []\n    self.row_template = None\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager.add","title":"add(self, row)","text":"

                                                                            Add row.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def add(self, row: List):\n\"\"\"Add row.\"\"\"\n    n_row = copy.copy(row)\n    t_row = self.row_template\n    if t_row:\n        for index in range(3):\n            if n_row[index] == t_row[index]:\n                n_row[index] = None\n    self.rows.append(n_row)\n    self.row_template = row\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.ContentManager.get_content","title":"get_content(self, level)","text":"

                                                                            Get content.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def get_content(self, level: str) -> List:\n\"\"\"Get content.\"\"\"\n    if level == level_control:\n        rval = self._get_content_by_control()\n    else:\n        rval = self._get_content_by_statement()\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper","title":" CsvHelper ","text":"

                                                                            Csv Helper.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            class CsvHelper:\n\"\"\"Csv Helper.\"\"\"\n\n    def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n        self.path = path\n\n    def write(self, rows: List[List[str]]) -> None:\n\"\"\"Write csv file.\"\"\"\n        with open(self.path, 'w', newline='', encoding='utf-8') as output:\n            csv_writer = csv.writer(output, delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n            for row in rows:\n                csv_writer.writerow(row)\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper.__init__","title":"__init__(self, path) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def __init__(self, path) -> None:\n\"\"\"Initialize.\"\"\"\n    self.path = path\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.CsvHelper.write","title":"write(self, rows)","text":"

                                                                            Write csv file.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def write(self, rows: List[List[str]]) -> None:\n\"\"\"Write csv file.\"\"\"\n    with open(self.path, 'w', newline='', encoding='utf-8') as output:\n        csv_writer = csv.writer(output, delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n        for row in rows:\n            csv_writer.writerow(row)\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv","title":" OscalCatalogToCsv (TaskBase) ","text":"

                                                                            Task to transform OSCAL catalog to .csv.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            class OscalCatalogToCsv(TaskBase):\n\"\"\"\n    Task to transform OSCAL catalog to .csv.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'oscal-catalog-to-csv'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info('Purpose: Create .csv from OSCAL catalog.')\n        logger.info('')\n        logger.info('Configuration flags sit under [task.oscal-catalog-to-csv]:')\n        text1 = '  input-file             = '\n        text2 = '(required) path of file to read the catalog.'\n        logger.info(text1 + text2)\n        text1 = '  output-dir             = '\n        text2 = '(required) path of directory to write the generated .csv file.'\n        logger.info(text1 + text2)\n        text1 = '  output-name            = '\n        text2 = '(optional) name of the generated .csv file [default is name of input file with .csv suffix].'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite       = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n        text1 = '  level                  = '\n        text2 = f'(optional) one of: {level_control} or {level_statement} [default].'\n        logger.info(text1 + text2)\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Wrap the execute for exception handling.\"\"\"\n        # config processing\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        # input\n        ifile = self._config.get('input-file')\n        if not ifile:\n            logger.warning('input-file missing')\n            return TaskOutcome('failure')\n        ipth = pathlib.Path(ifile)\n        # overwrite\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # output\n        odir = self._config.get('output-dir')\n        if not odir:\n            logger.warning('output-dir missing')\n            return TaskOutcome('failure')\n        opth = pathlib.Path(odir)\n        opth.mkdir(exist_ok=True, parents=True)\n        iname = ipth.name.split('.')[0]\n        oname = self._config.get('output-name', f'{iname}.csv')\n        opth = opth / oname\n        if not self._overwrite and opth.exists():\n            logger.warning(f'output: {opth} already exists')\n            return TaskOutcome('failure')\n        csv_helper = CsvHelper(opth)\n        # level\n        level = self._config.get('level', level_default)\n        if level not in level_list:\n            logger.warning(f'level: {level} unknown')\n            return TaskOutcome('failure')\n        # helper\n        catalog_helper = CatalogHelper(ipth)\n        # process\n        content_manager = ContentManager(catalog_helper)\n        rows = content_manager.get_content(level)\n        # write\n        csv_helper.write(rows)\n        logger.info(f'output-file: {opth}')\n        # success\n        return TaskOutcome('success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info('Purpose: Create .csv from OSCAL catalog.')\n    logger.info('')\n    logger.info('Configuration flags sit under [task.oscal-catalog-to-csv]:')\n    text1 = '  input-file             = '\n    text2 = '(required) path of file to read the catalog.'\n    logger.info(text1 + text2)\n    text1 = '  output-dir             = '\n    text2 = '(required) path of directory to write the generated .csv file.'\n    logger.info(text1 + text2)\n    text1 = '  output-name            = '\n    text2 = '(optional) name of the generated .csv file [default is name of input file with .csv suffix].'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite       = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n    text1 = '  level                  = '\n    text2 = f'(optional) one of: {level_control} or {level_statement} [default].'\n    logger.info(text1 + text2)\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.OscalCatalogToCsv.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv-functions","title":"Functions","text":""},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.convert_control_id","title":"convert_control_id(control_id)","text":"

                                                                            Convert control id.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def convert_control_id(control_id: str) -> str:\n\"\"\"Convert control id.\"\"\"\n    rval = copy.copy(control_id)\n    rval = rval.upper()\n    if '.' in rval:\n        rval = rval.replace('.', '(')\n        rval = rval + ')'\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.convert_smt_id","title":"convert_smt_id(smt_id)","text":"

                                                                            Convert smt id.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def convert_smt_id(smt_id: str) -> str:\n\"\"\"Convert smt id.\"\"\"\n    parts = smt_id.split('_smt')\n    seg1 = convert_control_id(parts[0])\n    seg2 = ''\n    if len(parts) == 2:\n        seg2 = parts[1]\n        if '.' in seg2:\n            seg2 = seg2.replace('.', '(')\n            seg2 = seg2 + ')'\n    rval = f'{seg1}{seg2}'\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_catalog_to_csv/#trestle.tasks.oscal_catalog_to_csv.join_str","title":"join_str(s1, s2, sep=' ')","text":"

                                                                            Join strings.

                                                                            Source code in trestle/tasks/oscal_catalog_to_csv.py
                                                                            def join_str(s1: Optional[str], s2: Optional[str], sep: str = ' ') -> Optional[str]:\n\"\"\"Join strings.\"\"\"\n    if s1 is None:\n        rval = s2\n    elif s2 is None:\n        rval = s1\n    else:\n        rval = f'{s1}{sep}{s2}'\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/","title":"oscal_profile_to_osco_profile","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile","title":"trestle.tasks.oscal_profile_to_osco_profile","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco","title":" ProfileToOsco (TaskBase) ","text":"

                                                                            Task to convert Profile to OSC yaml.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                                                            class ProfileToOsco(TaskBase):\n\"\"\"\n    Task to convert Profile to OSC yaml.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'oscal-profile-to-osco-profile'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task oscal-profile-to-osco-profile.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Open Security Controls Assessment Language (OSCAL) Profile '\n            + 'into Open Shift Compliance Operator (OSCO) .yaml file.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.oscal-profile-to-osco-profile]:')\n        logger.info('  input-file = (required) path of the input file comprising OSCAL profile.')\n        logger.info('  output-dir = (required) path of the output directory comprising synthesized .yaml file.')\n        logger.info(\n            '  output-name = (optional) name of created file in output directory, default is osco-profile.yaml.'\n        )\n        logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n        logger.info(\n            '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n        )\n        logger.info('')\n        logger.info('Operation: The specified input profile is transformed into OSCO .yaml.')\n        logger.info('')\n        logger.info('Notes:')\n        note11 = '[1] The input-file OSCAL profile should specify a metadata property with'\n        note12 = 'name \"osco_version\" and value of the form \"0.1.46\".'\n        note13 = 'The value corresponds with the OpenShift Compliance Operator (OSCO) version'\n        note14 = 'and affects the format of the emitted yaml.'\n        note15 = 'If not specified, the default is \"0.1.46\".'\n        logger.info(f'{note11} {note12} {note13} {note14} {note15}')\n        note21 = '[2] For OSCO version \"0.1.39\" and prior no \"description\" is emitted for \"spec\".'\n        logger.info(f'{note21}')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.warning(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        # check config\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome('failure')\n        # input-file\n        input_file = self._config.get('input-file')\n        if input_file is None:\n            logger.warning('config missing \"input-file\"')\n            return TaskOutcome('failure')\n        logger.info(f'input-file: {input_file}')\n        input_path = pathlib.Path(input_file)\n        # output-dir\n        output_dir = self._config.get('output-dir')\n        if output_dir is None:\n            logger.warning('config missing \"output-dir\"')\n            return TaskOutcome('failure')\n        output_path = pathlib.Path(output_dir)\n        # insure output dir exists\n        output_path.mkdir(exist_ok=True, parents=True)\n        # output file path\n        output_name = self._config.get('output-name', 'osco-profile.yaml')\n        output_filepath = pathlib.Path(output_dir, output_name)\n        logger.info(f'output-file: {output_filepath}')\n        # overwrite\n        overwrite = self._config.getboolean('output-overwrite', True)\n        if not overwrite and pathlib.Path(output_filepath).exists():\n            logger.warning(f'output-file: {output_filepath} already exists')\n            return TaskOutcome('failure')\n        # read input\n        profile = Profile.oscal_read(input_path)\n        # transform\n        transformer = OscalProfileToOscoProfileTransformer()\n        ydata = json.loads(transformer.transform(profile))\n        # write output\n        yaml = YAML(typ='safe')\n        yaml.default_flow_style = False\n        with open(output_filepath, 'w') as outfile:\n            yaml.dump(ydata, outfile)\n        # success\n        return TaskOutcome('success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task oscal-profile-to-osco-profile.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task oscal-profile-to-osco-profile.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.warning(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Open Security Controls Assessment Language (OSCAL) Profile '\n        + 'into Open Shift Compliance Operator (OSCO) .yaml file.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.oscal-profile-to-osco-profile]:')\n    logger.info('  input-file = (required) path of the input file comprising OSCAL profile.')\n    logger.info('  output-dir = (required) path of the output directory comprising synthesized .yaml file.')\n    logger.info(\n        '  output-name = (optional) name of created file in output directory, default is osco-profile.yaml.'\n    )\n    logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n    logger.info(\n        '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n    )\n    logger.info('')\n    logger.info('Operation: The specified input profile is transformed into OSCO .yaml.')\n    logger.info('')\n    logger.info('Notes:')\n    note11 = '[1] The input-file OSCAL profile should specify a metadata property with'\n    note12 = 'name \"osco_version\" and value of the form \"0.1.46\".'\n    note13 = 'The value corresponds with the OpenShift Compliance Operator (OSCO) version'\n    note14 = 'and affects the format of the emitted yaml.'\n    note15 = 'If not specified, the default is \"0.1.46\".'\n    logger.info(f'{note11} {note12} {note13} {note14} {note15}')\n    note21 = '[2] For OSCO version \"0.1.39\" and prior no \"description\" is emitted for \"spec\".'\n    logger.info(f'{note21}')\n
                                                                            "},{"location":"api_reference/trestle.tasks.oscal_profile_to_osco_profile/#trestle.tasks.oscal_profile_to_osco_profile.ProfileToOsco.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/oscal_profile_to_osco_profile.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/","title":"osco_result_to_oscal_ar","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar","title":"trestle.tasks.osco_result_to_oscal_ar","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR","title":" OscoResultToOscalAR (TaskBase) ","text":"

                                                                            Task to convert Osco result to OSCAL json.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                                                            class OscoResultToOscalAR(TaskBase):\n\"\"\"\n    Task to convert Osco result to OSCAL json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'osco-result-to-oscal-ar'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task osco-result-to-oscal-ar.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Osco files into Open Security Controls Assessment Language (OSCAL) '\n            + 'partial results files.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.osco-result-to-oscal-ar]:')\n        logger.info(\n            '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n        )\n        logger.info('  input-dir = (required) the path of the input directory comprising Osco results.')\n        logger.info(\n            '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n        )\n        logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n        logger.info(\n            '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n        )\n        logger.info(\n            '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n            + ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Osco '\n            + ' result is used if present, otherwise current time is used.'\n        )\n        logger.info('')\n        logger.info(\n            'Operation: A transformation is performed on one or more Osco input files to produce output in OSCAL '\n            + 'partial results format.'\n        )\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        self._simulate = True\n        return self._transform()\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        self._simulate = False\n        return self._transform()\n\n    def _transform(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        try:\n            return self._transform_work()\n        except Exception:\n            logger.debug(traceback.format_exc())\n            mode = ''\n            if self._simulate:\n                mode = 'simulated-'\n            return TaskOutcome(mode + 'failure')\n\n    def _transform_work(self) -> TaskOutcome:\n\"\"\"\n        Perform transformation work steps.\n\n        Work steps: read input, process, write output, display analysis\n        \"\"\"\n        mode = ''\n        if self._simulate:\n            mode = 'simulated-'\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome(mode + 'failure')\n        # config required input & output dirs\n        try:\n            idir = self._config['input-dir']\n            ipth = pathlib.Path(idir)\n            odir = self._config['output-dir']\n            opth = pathlib.Path(odir)\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            return TaskOutcome(mode + 'failure')\n        # config optional overwrite & quiet\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        quiet = self._config.get('quiet', False)\n        self._verbose = not self._simulate and not quiet\n        # config optional timestamp\n        timestamp = self._config.get('timestamp')\n        if timestamp is not None:\n            try:\n                OscoTransformer.set_timestamp(timestamp)\n            except Exception:\n                logger.warning('config invalid \"timestamp\"')\n                return TaskOutcome(mode + 'failure')\n        # config optional performance\n        modes = {\n            'checking': self._config.getboolean('checking', False),\n        }\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # process\n        for ifile in sorted(ipth.iterdir()):\n            if ifile.suffix not in ['.json', '.jsn', '.yaml', '.yml', '.xml']:\n                continue\n            blob = self._read_file(ifile)\n            osco_transformer = OscoTransformer()\n            osco_transformer.set_modes(modes)\n            results = osco_transformer.transform(blob)\n            oname = ifile.stem + '.oscal' + '.json'\n            ofile = opth / oname\n            if not self._overwrite and pathlib.Path(ofile).exists():\n                logger.warning(f'output: {ofile} already exists')\n                return TaskOutcome(mode + 'failure')\n            self._write_file(results, ofile)\n            self._show_analysis(osco_transformer)\n        return TaskOutcome(mode + 'success')\n\n    def _read_file(self, ifile: str) -> str:\n\"\"\"Read raw input file.\"\"\"\n        if not self._simulate and self._verbose:\n            logger.info(f'input: {ifile}')\n        with open(ifile, encoding=const.FILE_ENCODING) as fp:\n            blob = fp.read()\n        return blob\n\n    def _write_file(self, result: str, ofile: str) -> None:\n\"\"\"Write oscal results file.\"\"\"\n        if not self._simulate:\n            if self._verbose:\n                logger.info(f'output: {ofile}')\n            result.oscal_write(pathlib.Path(ofile))\n\n    def _show_analysis(self, osco_transformer: OscoTransformer) -> None:\n\"\"\"Show analysis.\"\"\"\n        if not self._simulate and self._verbose:\n            analysis = osco_transformer.analysis\n            for line in analysis:\n                logger.info(line)\n
                                                                            "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task osco-result-to-oscal-ar.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task osco-result-to-oscal-ar.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    self._simulate = False\n    return self._transform()\n
                                                                            "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Osco files into Open Security Controls Assessment Language (OSCAL) '\n        + 'partial results files.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.osco-result-to-oscal-ar]:')\n    logger.info(\n        '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n    )\n    logger.info('  input-dir = (required) the path of the input directory comprising Osco results.')\n    logger.info(\n        '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n    )\n    logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n    logger.info(\n        '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n    )\n    logger.info(\n        '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n        + ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Osco '\n        + ' result is used if present, otherwise current time is used.'\n    )\n    logger.info('')\n    logger.info(\n        'Operation: A transformation is performed on one or more Osco input files to produce output in OSCAL '\n        + 'partial results format.'\n    )\n
                                                                            "},{"location":"api_reference/trestle.tasks.osco_result_to_oscal_ar/#trestle.tasks.osco_result_to_oscal_ar.OscoResultToOscalAR.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/osco_result_to_oscal_ar.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    self._simulate = True\n    return self._transform()\n
                                                                            "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/","title":"tanium_result_to_oscal_ar","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar","title":"trestle.tasks.tanium_result_to_oscal_ar","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR","title":" TaniumResultToOscalAR (TaskBase) ","text":"

                                                                            Task to convert Tanium result to OSCAL json.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                                                            class TaniumResultToOscalAR(TaskBase):\n\"\"\"\n    Task to convert Tanium result to OSCAL json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'tanium-result-to-oscal-ar'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task tanium-result-to-oscal-ar.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Tanium files into Open Security Controls Assessment Language (OSCAL) results objects'\n            + 'and serialize to a file.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.tanium-result-to-oscal-ar]:')\n        logger.info('  blocksize = (optional) the desired number Tanuim result input lines to process per CPU.')\n        logger.info('  cpus-max  = (optional) the desired maximum number of CPUs to employ, default is 1.')\n        logger.info('  cpus-min  = (optional) the desired minimum number of CPUs to employ.')\n        logger.info('  aggregate = (optional) True indicates employ properties aggregation, default is True.')\n        logger.info('  caching   = (optional) True indicates employ object caching, default is True.')\n        logger.info(\n            '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n        )\n        logger.info('  input-dir = (required) the path of the input directory comprising Tanium results.')\n        logger.info(\n            '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n        )\n        logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n        logger.info(\n            '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n        )\n        logger.info(\n            '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n            + '2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Tanium '\n            + 'result is used if present, otherwise current time is used.'\n        )\n        logger.info('')\n        logger.info(\n            'Operation: A transformation is performed on one or more Tanium input files to produce output in '\n            + 'OSCAL partial results format.'\n        )\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        self._simulate = True\n        return self._transform()\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        self._simulate = False\n        return self._transform()\n\n    def _transform(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        try:\n            return self._transform_work()\n        except Exception:\n            logger.info(traceback.format_exc())\n            mode = ''\n            if self._simulate:\n                mode = 'simulated-'\n            return TaskOutcome(mode + 'failure')\n\n    def _transform_work(self) -> TaskOutcome:\n\"\"\"\n        Perform the transformation work.\n\n        Transformation work steps: read input, process, write output, display analysis.\n        \"\"\"\n        mode = ''\n        if self._simulate:\n            mode = 'simulated-'\n        if not self._config:\n            logger.warning('Config missing')\n            return TaskOutcome(mode + 'failure')\n        # config required input & output dirs\n        try:\n            idir = self._config['input-dir']\n            ipth = pathlib.Path(idir)\n            odir = self._config['output-dir']\n            opth = pathlib.Path(odir)\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            return TaskOutcome(mode + 'failure')\n        # config optional overwrite & quiet\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        quiet = self._config.get('quiet', False)\n        self._verbose = not self._simulate and not quiet\n        # config optional timestamp\n        timestamp = self._config.get('timestamp')\n        if timestamp is not None:\n            try:\n                TaniumTransformer.set_timestamp(timestamp)\n            except Exception:\n                logger.warning('config invalid \"timestamp\"')\n                return TaskOutcome(mode + 'failure')\n        # config optional performance\n        modes = {\n            'blocksize': self._config.getint('blocksize', 10000),\n            'cpus_max': self._config.getint('cpus-max', 1),\n            'cpus_min': self._config.getint('cpus-min', 1),\n            'aggregate': self._config.getboolean('aggregate', True),\n            'caching': self._config.getboolean('caching', True),\n            'checking': self._config.getboolean('checking', False),\n        }\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # process\n        for ifile in sorted(ipth.iterdir()):\n            blob = self._read_file(ifile)\n            tanium_transformer = TaniumTransformer()\n            tanium_transformer.set_modes(modes)\n            results = tanium_transformer.transform(blob)\n            oname = ifile.stem + '.oscal' + '.json'\n            ofile = opth / oname\n            if not self._overwrite and pathlib.Path(ofile).exists():\n                logger.warning(f'output: {ofile} already exists')\n                return TaskOutcome(mode + 'failure')\n            self._write_file(results, ofile)\n            self._show_analysis(tanium_transformer)\n        return TaskOutcome(mode + 'success')\n\n    def _read_file(self, ifile: str) -> str:\n\"\"\"Read raw input file.\"\"\"\n        if not self._simulate and self._verbose:\n            logger.info(f'input: {ifile}')\n        with open(ifile, 'r', encoding=const.FILE_ENCODING) as fp:\n            blob = fp.read()\n        return blob\n\n    def _write_file(self, result: str, ofile: str) -> None:\n\"\"\"Write oscal results file.\"\"\"\n        if not self._simulate:\n            if self._verbose:\n                logger.info(f'output: {ofile}')\n            result.oscal_write(pathlib.Path(ofile))\n\n    def _show_analysis(self, tanium_transformer: TaniumTransformer) -> None:\n\"\"\"Show analysis.\"\"\"\n        if not self._simulate and self._verbose:\n            analysis = tanium_transformer.analysis\n            for line in analysis:\n                logger.info(line)\n
                                                                            "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task tanium-result-to-oscal-ar.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task tanium-result-to-oscal-ar.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    self._simulate = False\n    return self._transform()\n
                                                                            "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Tanium files into Open Security Controls Assessment Language (OSCAL) results objects'\n        + 'and serialize to a file.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.tanium-result-to-oscal-ar]:')\n    logger.info('  blocksize = (optional) the desired number Tanuim result input lines to process per CPU.')\n    logger.info('  cpus-max  = (optional) the desired maximum number of CPUs to employ, default is 1.')\n    logger.info('  cpus-min  = (optional) the desired minimum number of CPUs to employ.')\n    logger.info('  aggregate = (optional) True indicates employ properties aggregation, default is True.')\n    logger.info('  caching   = (optional) True indicates employ object caching, default is True.')\n    logger.info(\n        '  checking  = (optional) True indicates perform strict checking of OSCAL properties, default is False.'\n    )\n    logger.info('  input-dir = (required) the path of the input directory comprising Tanium results.')\n    logger.info(\n        '  output-dir = (required) the path of the output directory comprising synthesized OSCAL .json files.'\n    )\n    logger.info('  output-overwrite = (optional) true [default] or false; replace existing output when true.')\n    logger.info(\n        '  quiet = (optional) true or false [default]; display file creations and rules analysis when false.'\n    )\n    logger.info(\n        '  timestamp = (optional) timestamp for the Observations in ISO 8601 format, such as '\n        + '2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Tanium '\n        + 'result is used if present, otherwise current time is used.'\n    )\n    logger.info('')\n    logger.info(\n        'Operation: A transformation is performed on one or more Tanium input files to produce output in '\n        + 'OSCAL partial results format.'\n    )\n
                                                                            "},{"location":"api_reference/trestle.tasks.tanium_result_to_oscal_ar/#trestle.tasks.tanium_result_to_oscal_ar.TaniumResultToOscalAR.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/tanium_result_to_oscal_ar.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    self._simulate = True\n    return self._transform()\n
                                                                            "},{"location":"api_reference/trestle.tasks.transform/","title":"transform","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.transform/#trestle.tasks.transform","title":"trestle.tasks.transform","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/","title":"xccdf_result_to_oscal_ar","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar","title":"trestle.tasks.xccdf_result_to_oscal_ar","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.default_description","title":"default_description","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.default_title","title":"default_title","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.default_type","title":"default_type","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR","title":" XccdfResultToOscalAR (TaskBase) ","text":"

                                                                            Task to convert Xccdf result to OSCAL json.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                                                            class XccdfResultToOscalAR(TaskBase):\n\"\"\"\n    Task to convert Xccdf result to OSCAL json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'xccdf-result-to-oscal-ar'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task xccdf-result-to-oscal-ar.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        opt = '(optional)'\n        req = '(required)'\n        logger.info(f'Help information for {self.name} task.')\n        logger.info('')\n        logger.info(\n            'Purpose: Transform Xccdf files into Open Security Controls Assessment Language (OSCAL) '\n            + 'partial results files.'\n        )\n        logger.info('')\n        logger.info('Configuration flags sit under [task.xccdf-result-to-oscal-ar]:')\n        #\n        t1 = f'  input-dir              = {req} '\n        t2 = 'the path of the input directory comprising Xccdf results.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  output-dir             = {req} '\n        t2 = 'the path of the output directory comprising synthesized OSCAL .json files.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  checking               = {opt} '\n        t2 = 'True indicates perform strict checking of OSCAL properties, default is False.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  output-overwrite       = {opt} '\n        t2 = 'true [default] or false; replace existing output when true.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  quiet                  = {opt} '\n        t2 = 'true or false [default]; display file creations and rules analysis when false.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  title                  = {opt} '\n        t2 = f'default={default_title}.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  description            = {opt} '\n        t2 = f'default={default_description}.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  type                   = {opt} '\n        t2 = f'default={default_type}.'\n        logger.info(f'{t1}{t2}')\n        t1 = f'  property-name-to-class = {opt} '\n        t2 = 'list of name:class pairs for tagging named property with class, '\n        t3 = 'e.g. \"target:scc_inventory_item_id, version:scc_check_version\".'\n        logger.info(f'{t1}{t2}{t3}')\n        t1 = f'  timestamp              = {opt} '\n        t2 = 'timestamp for the Observations in ISO 8601 format, such as '\n        t3 = ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Xccdf '\n        t4 = ' result is used if present, otherwise current time is used.'\n        logger.info(f'{t1}{t2}{t3}{t4}')\n        #\n        logger.info('')\n        logger.info(\n            'Operation: A transformation is performed on one or more Xccdf input files to produce output in OSCAL '\n            + 'partial results format.'\n        )\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        self._simulate = True\n        return self._transform()\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n        self._simulate = False\n        return self._transform()\n\n    def _transform(self) -> TaskOutcome:\n\"\"\"Perform transformation.\"\"\"\n        try:\n            return self._transform_work()\n        except Exception:\n            logger.debug(traceback.format_exc())\n            mode = ''\n            if self._simulate:\n                mode = 'simulated-'\n            return TaskOutcome(mode + 'failure')\n\n    def _transform_work(self) -> TaskOutcome:\n\"\"\"\n        Perform transformation work steps.\n\n        Work steps: read input, process, write output, display analysis\n        \"\"\"\n        mode = ''\n        if self._simulate:\n            mode = 'simulated-'\n        if not self._config:\n            logger.warning('config missing')\n            return TaskOutcome(mode + 'failure')\n        # config required input & output dirs\n        try:\n            idir = self._config['input-dir']\n            ipth = pathlib.Path(idir)\n            odir = self._config['output-dir']\n            opth = pathlib.Path(odir)\n        except KeyError as e:\n            logger.debug(f'key {e.args[0]} missing')\n            return TaskOutcome(mode + 'failure')\n        # config optional overwrite & quiet\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        quiet = self._config.get('quiet', False)\n        self._verbose = not self._simulate and not quiet\n        # title, description, type\n        title = self._config.get('title', default_title)\n        description = self._config.get('description', default_description)\n        type_ = self._config.get('type', default_type)\n        # property-name-to-class\n        tags = self._get_tags()\n        # config optional timestamp\n        timestamp = self._config.get('timestamp')\n        if timestamp is not None:\n            try:\n                XccdfTransformer.set_timestamp(timestamp)\n            except Exception:\n                logger.warning('config invalid \"timestamp\"')\n                return TaskOutcome(mode + 'failure')\n        # config optional performance\n        modes = {\n            'checking': self._config.getboolean('checking', False),\n        }\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # process\n        for ifile in sorted(ipth.iterdir()):\n            if ifile.suffix not in ['.json', '.jsn', '.yaml', '.yml', '.xml']:\n                continue\n            blob = self._read_file(ifile)\n            xccdf_transformer = XccdfTransformer()\n            xccdf_transformer.set_title(title)\n            xccdf_transformer.set_description(description)\n            xccdf_transformer.set_type(type_)\n            xccdf_transformer.set_modes(modes)\n            xccdf_transformer.set_tags(tags)\n            results = xccdf_transformer.transform(blob)\n            oname = ifile.stem + '.oscal' + '.json'\n            ofile = opth / oname\n            if not self._overwrite and pathlib.Path(ofile).exists():\n                logger.warning(f'output: {ofile} already exists')\n                return TaskOutcome(mode + 'failure')\n            self._write_file(results, ofile)\n            self._show_analysis(xccdf_transformer)\n        return TaskOutcome(mode + 'success')\n\n    def _get_tags(self) -> Dict:\n\"\"\"Get property name to class tags, if any.\"\"\"\n        tags = {}\n        data = self._config.get('property-name-to-class')\n        if data is not None:\n            for item in data.split(','):\n                item = item.strip()\n                parts = item.split(':')\n                if len(parts) == 2:\n                    name = parts[0]\n                    value = parts[1]\n                    tags[name] = value\n        return tags\n\n    def _read_file(self, ifile: str) -> str:\n\"\"\"Read raw input file.\"\"\"\n        if not self._simulate and self._verbose:\n            logger.info(f'input: {ifile}')\n        with open(ifile, encoding=const.FILE_ENCODING) as fp:\n            blob = fp.read()\n        return blob\n\n    def _write_file(self, result: str, ofile: str) -> None:\n\"\"\"Write oscal results file.\"\"\"\n        if not self._simulate:\n            if self._verbose:\n                logger.info(f'output: {ofile}')\n            result.oscal_write(pathlib.Path(ofile))\n\n    def _show_analysis(self, xccdf_transformer: XccdfTransformer) -> None:\n\"\"\"Show analysis.\"\"\"\n        if not self._simulate and self._verbose:\n            analysis = xccdf_transformer.analysis\n            for line in analysis:\n                logger.info(line)\n
                                                                            "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task xccdf-result-to-oscal-ar.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task xccdf-result-to-oscal-ar.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n
                                                                            "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.execute","title":"execute(self)","text":"

                                                                            Provide an actual outcome.

                                                                            Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an actual outcome.\"\"\"\n    self._simulate = False\n    return self._transform()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    opt = '(optional)'\n    req = '(required)'\n    logger.info(f'Help information for {self.name} task.')\n    logger.info('')\n    logger.info(\n        'Purpose: Transform Xccdf files into Open Security Controls Assessment Language (OSCAL) '\n        + 'partial results files.'\n    )\n    logger.info('')\n    logger.info('Configuration flags sit under [task.xccdf-result-to-oscal-ar]:')\n    #\n    t1 = f'  input-dir              = {req} '\n    t2 = 'the path of the input directory comprising Xccdf results.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  output-dir             = {req} '\n    t2 = 'the path of the output directory comprising synthesized OSCAL .json files.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  checking               = {opt} '\n    t2 = 'True indicates perform strict checking of OSCAL properties, default is False.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  output-overwrite       = {opt} '\n    t2 = 'true [default] or false; replace existing output when true.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  quiet                  = {opt} '\n    t2 = 'true or false [default]; display file creations and rules analysis when false.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  title                  = {opt} '\n    t2 = f'default={default_title}.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  description            = {opt} '\n    t2 = f'default={default_description}.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  type                   = {opt} '\n    t2 = f'default={default_type}.'\n    logger.info(f'{t1}{t2}')\n    t1 = f'  property-name-to-class = {opt} '\n    t2 = 'list of name:class pairs for tagging named property with class, '\n    t3 = 'e.g. \"target:scc_inventory_item_id, version:scc_check_version\".'\n    logger.info(f'{t1}{t2}{t3}')\n    t1 = f'  timestamp              = {opt} '\n    t2 = 'timestamp for the Observations in ISO 8601 format, such as '\n    t3 = ' 2021-01-04T00:05:23+04:00 for example; if not specified then value for \"Timestamp\" key in the Xccdf '\n    t4 = ' result is used if present, otherwise current time is used.'\n    logger.info(f'{t1}{t2}{t3}{t4}')\n    #\n    logger.info('')\n    logger.info(\n        'Operation: A transformation is performed on one or more Xccdf input files to produce output in OSCAL '\n        + 'partial results format.'\n    )\n
                                                                            "},{"location":"api_reference/trestle.tasks.xccdf_result_to_oscal_ar/#trestle.tasks.xccdf_result_to_oscal_ar.XccdfResultToOscalAR.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/xccdf_result_to_oscal_ar.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    self._simulate = True\n    return self._transform()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/","title":"xlsx_helper","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper","title":"trestle.tasks.xlsx_helper","text":"

                                                                            XLSX utilities.

                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column","title":" Column ","text":"

                                                                            Spread sheet columns.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            class Column():\n\"\"\"Spread sheet columns.\"\"\"\n\n    control_id = 'ControlId'\n    control_text = 'ControlText'\n    goal_name_id = 'goal_name_id'\n    goal_version = 'goal_version'\n    rule_name_id = 'rule_name_id'\n    rule_version = 'rule_version'\n    nist_mappings = 'NIST Mappings'\n    resource_title = 'ResourceTitle'\n    parameter_opt_parm = 'Parameter [optional parameter]'\n    values_alternatives = 'Values default , [alternatives]'\n    filter_column = None\n\n    tokens_nist_mappings = nist_mappings.split()\n    tokens_parameter_opt_parm = parameter_opt_parm.split()\n    rename_parameter_opt_parm = 'ParameterName'\n    tokens_values_alternatives = values_alternatives.split()\n    rename_values_alternatives = 'ParameterValue'\n\n    help_list = []\n    text1 = '                      '\n    text2 = f'column \"{control_id}\" contains control ID.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{control_text}\" contains control text.'\n    help_list.append(text1 + text2)\n    text2 = f'columns \"{nist_mappings}\" contain NIST control mappings.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{resource_title}\" contains component name.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{goal_name_id}\" contains goal name.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{goal_version}\" contains goal version.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{rule_name_id}\" contains rule name.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{rule_version}\" contains rule version.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{parameter_opt_parm}\" contains parameter name + description, separated by newline.'\n    help_list.append(text1 + text2)\n    text2 = f'column \"{values_alternatives}\" contains parameter values.'\n    help_list.append(text1 + text2)\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.control_id","title":"control_id","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.control_text","title":"control_text","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.filter_column","title":"filter_column","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.goal_name_id","title":"goal_name_id","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.goal_version","title":"goal_version","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.help_list","title":"help_list","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.nist_mappings","title":"nist_mappings","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.parameter_opt_parm","title":"parameter_opt_parm","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rename_parameter_opt_parm","title":"rename_parameter_opt_parm","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rename_values_alternatives","title":"rename_values_alternatives","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.resource_title","title":"resource_title","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rule_name_id","title":"rule_name_id","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.rule_version","title":"rule_version","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.text1","title":"text1","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.text2","title":"text2","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.tokens_nist_mappings","title":"tokens_nist_mappings","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.tokens_parameter_opt_parm","title":"tokens_parameter_opt_parm","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.tokens_values_alternatives","title":"tokens_values_alternatives","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.Column.values_alternatives","title":"values_alternatives","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper","title":" XlsxHelper ","text":"

                                                                            Xlsx Helper common functions and assistance navigating spread sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            class XlsxHelper:\n\"\"\"Xlsx Helper common functions and assistance navigating spread sheet.\"\"\"\n\n    by_goal = 'by-goal'\n    by_rule = 'by-rule'\n    by_control = 'by-control'\n    by_check = 'by-check'\n\n    profile_types = [by_goal, by_rule, by_control, by_check]\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._column = Column()\n\n    def print_info(self, name, oscal_name) -> None:\n\"\"\"Print the help string.\"\"\"\n        logger.info(f'Help information for {name} task.')\n        logger.info('')\n        logger.info(f'Purpose: From spread sheet and catalog produce OSCAL {oscal_name} file.')\n        logger.info('')\n        logger.info(f'Configuration flags sit under [task.{name}]:')\n        if oscal_name == 'component_definition':\n            text1 = '  catalog-file      = '\n            text2 = '(required) the path of the OSCAL catalog file.'\n            logger.info(text1 + text2)\n        text1 = '  spread-sheet-file = '\n        text2 = '(required) the path of the spread sheet file.'\n        logger.info(text1 + text2)\n        text1 = '  work-sheet-name   = '\n        text2 = '(required) the name of the work sheet in the spread sheet file.'\n        logger.info(text1 + text2)\n        for line in self._column.help_list:\n            logger.info(line)\n        text1 = '  output-dir        = '\n        text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n        logger.info(text1 + text2)\n        text1 = '  output-overwrite  = '\n        text2 = '(optional) true [default] or false; replace existing output when true.'\n        logger.info(text1 + text2)\n        text1 = '  filter-column     = '\n        text2 = '(optional) column heading of yes/no values; process only \"yes\" rows.'\n        logger.info(text1 + text2)\n        text1 = '  profile-type      = '\n        text2 = f'(optional) one of {self.profile_types}'\n        logger.info(text1 + text2)\n\n    @property\n    def profile_type(self) -> str:\n\"\"\"Profile type.\"\"\"\n        return self._profile_type\n\n    def configure(self, task: TaskBase) -> bool:\n\"\"\"Configure.\"\"\"\n        if not task._config:\n            logger.warning('config missing')\n            return False\n        # config verbosity\n        quiet = task._config.get('quiet', False)\n        task._verbose = not quiet\n        # required for component-definition\n        if not self.configure_cd(task):\n            return False\n        # required for profile\n        if not self.configure_profile(task):\n            return False\n        # optional\n        self._column.filter_column = task._config.get('filter-column', None)\n        # config spread sheet\n        spread_sheet = task._config.get('spread-sheet-file')\n        if spread_sheet is None:\n            logger.warning('config missing \"spread-sheet\"')\n            return False\n        if not pathlib.Path(spread_sheet).exists():\n            logger.warning('\"spread-sheet\" not found')\n            return False\n        sheet_name = task._config.get('work-sheet-name')\n        if sheet_name is None:\n            logger.warning('config missing \"work-sheet-name\"')\n            return False\n        # announce spreadsheet\n        if task._verbose:\n            logger.info(f'input: {spread_sheet}')\n        # get profile type\n        if task.name == 'xlsx-to-oscal-profile':\n            self._profile_type = task._config.get('profile-type', self.profile_types[0])\n            if self._profile_type not in self.profile_types:\n                logger.warning(f'invalid \"profile-type\" {self._profile_type} ')\n                return False\n        else:\n            self._profile_type = None\n        # load spread sheet\n        self.load(spread_sheet, sheet_name)\n        return True\n\n    def configure_cd(self, task: TaskBase) -> bool:\n\"\"\"Configure cd.\"\"\"\n        if task.name == 'xlsx-to-oscal-cd':\n            catalog_file = task._config.get('catalog-file')\n            if catalog_file is None:\n                logger.warning('config missing \"catalog-file\"')\n                return False\n            try:\n                catalog = Catalog.oscal_read(pathlib.Path(catalog_file))\n                logger.debug(f'catalog: {catalog_file}')\n            except Exception as e:  # pragma: no cover\n                raise TrestleError(f'Error loading catalog {catalog_file}: {e}')\n            task.catalog_interface = CatalogInterface(catalog)\n        return True\n\n    def configure_profile(self, task: TaskBase) -> bool:\n\"\"\"Configure profile.\"\"\"\n        if task.name == 'xlsx-to-oscal-profile':\n            profile_title = task._config.get('profile-title')\n            if profile_title is None:\n                logger.warning('config missing \"profile-title\"')\n                return False\n            spread_sheet_url = task._config.get('spread-sheet-url')\n            if spread_sheet_url is None:\n                logger.warning('config missing \"spread-sheet-url\"')\n                return False\n        return True\n\n    def load(self, spread_sheet: str, sheet_name: str) -> None:\n\"\"\"Load.\"\"\"\n        self._spread_sheet = spread_sheet\n        self._sheet_name = sheet_name\n        self._wb = load_workbook(self._spread_sheet)\n        self._work_sheet = self._wb[self._sheet_name]\n        self._map_name_to_letters = {}\n        # accumulators\n        self.rows_missing_control_id = []\n        self.rows_missing_goal_name_id = []\n        self.rows_invalid_goal_name_id = []\n        self.rows_missing_rule_name_id = []\n        self.rows_invalid_rule_name_id = []\n        self.rows_invalid_parameter_name = []\n        self.rows_missing_controls = []\n        self.rows_missing_parameters = []\n        self.rows_missing_parameters_values = []\n        self.rows_filtered = []\n        # map columns\n        self._map_columns()\n\n    def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until control_id is None.\"\"\"\n        row = 1\n        rows_skipped_consecutive = 0\n        # assume no more data when 100 consecutve rows no control id\n        rows_skipped_consecutive_limit = 100\n        while True:\n            row = row + 1\n            control_id = self._get_control_id(row)\n            goal_id = self.get_goal_name_id(row)\n            if control_id is None and goal_id is None:\n                rows_skipped_consecutive += 1\n                if rows_skipped_consecutive < rows_skipped_consecutive_limit:\n                    continue\n                logger.debug(f'break: {row} {rows_skipped_consecutive}')\n                break\n            if control_id is None:\n                self._add_row(row, self.rows_missing_control_id)\n                continue\n            if goal_id is None:\n                self._add_row(row, self.rows_missing_goal_name_id)\n                continue\n            if self._is_filtered(row):\n                continue\n            yield row\n            rows_skipped_consecutive = 0\n\n    def _is_filtered(self, row) -> bool:\n\"\"\"Return True if row is to be skipped.\"\"\"\n        if self._column.filter_column is None:\n            return False\n        col = self._get_column_letter(self._column.filter_column)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            return False\n        if value.lower() != 'yes':\n            return False\n        self._add_row(row, self.rows_filtered)\n        return True\n\n    def get_goal_name_id(self, row: int, strict: bool = True) -> str:\n\"\"\"Get goal_name_id from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.goal_name_id)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            self._add_row(row, self.rows_missing_goal_name_id)\n        else:\n            value = str(value).strip()\n            if strict:\n                svalue = str(value).strip()\n                value = ''.join(str(svalue).split())\n                if value != svalue:\n                    self._add_row(row, self.rows_invalid_goal_name_id)\n        return value\n\n    def get_check_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get check_name_id from work_sheet.\"\"\"\n        return self.get_goal_name_id(row, strict)\n\n    def get_rule_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get rule_name_id from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.rule_name_id)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            self._add_row(row, self.rows_missing_rule_name_id)\n        else:\n            value = str(value).strip()\n            if strict:\n                svalue = str(value).strip()\n                value = ''.join(str(svalue).split())\n                if value != svalue:\n                    self._add_row(row, self.rows_invalid_rule_name_id)\n        return value\n\n    def get_parameter_usage(self, row: int) -> str:\n\"\"\"Get parameter_usage from work_sheet.\"\"\"\n        return self.get_goal_remarks(row)\n\n    def get_parameter_value_default(self, row: int) -> str:\n\"\"\"Get parameter_value_default from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.rename_values_alternatives)\n        value = self._work_sheet[col + str(row)].value\n        if value is not None:\n            value = str(value).split(',')[0].strip()\n        return value\n\n    def get_parameter_values(self, row: int) -> str:\n\"\"\"Get parameter_values from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.rename_values_alternatives)\n        value = self._work_sheet[col + str(row)].value\n        if value is None and self.get_parameter_name(row) is not None:\n            self._add_row(row, self.rows_missing_parameters_values)\n        # massage into comma separated list of values\n        else:\n            value = str(value).strip().replace(' ', '')\n            value = value.replace(',[]', '')\n            value = value.replace('[', '')\n            value = value.replace(']', '')\n            value = value.split(',')\n        return value\n\n    def _get_goal_text(self, row: int) -> str:\n\"\"\"Get goal_text from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.control_text)\n        goal_text = self._work_sheet[col + str(row)].value\n        # normalize & tokenize\n        value = goal_text.replace('\\t', ' ')\n        return value\n\n    def _get_goal_text_tokens(self, row: int) -> List[str]:\n\"\"\"Get goal_text tokens from work_sheet.\"\"\"\n        goal_text = self._get_goal_text(row)\n        tokens = goal_text.split()\n        return tokens\n\n    def get_goal_remarks(self, row: int) -> str:\n\"\"\"Get goal_remarks from work_sheet.\"\"\"\n        tokens = self._get_goal_text_tokens(row)\n        # replace \"Check whether\" with \"Ensure\", if present\n        if tokens:\n            if tokens[0] == 'Check':\n                if len(tokens) > 1:\n                    if tokens[1] == 'whether':\n                        tokens.pop(0)\n                tokens[0] = 'Ensure'\n        value = ' '.join(tokens)\n        return value\n\n    def get_controls(self, row: int) -> Dict[str, List[str]]:\n\"\"\"Produce dict of controls mapped to statements.\n\n        Example: {'au-2': ['(a)', '(d)'], 'au-12': [], 'si-4': ['(a)', '(b)', '(c)']}\n        \"\"\"\n        value = {}\n        for col in self._get_column_letter(self._column.nist_mappings):\n            control = self._work_sheet[col + str(row)].value\n            if control is None:\n                continue\n            # remove blanks\n            control = ''.join(control.split())\n            if len(control) < 1 or control.lower() == 'none':\n                continue\n            # remove rhs of : inclusive\n            if ':' in control:\n                control = control.split(':')[0]\n            # remove alphabet parts of control & accumulate in statements\n            control, statements = self._normalize_control(control)\n            # skip bogus control made up if dashes only\n            if len(control.replace('-', '')) == 0:\n                continue\n            if control not in value.keys():\n                value[control] = statements\n        if len(value.keys()) == 0:\n            self._add_row(row, self.rows_missing_controls)\n        logger.debug(f'row: {row} controls {value}')\n        return value\n\n    def get_component_name(self, row: int) -> str:\n\"\"\"Get component_name from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.resource_title)\n        value = self._work_sheet[col + str(row)].value\n        if value is None:\n            raise RuntimeError(f'row {row} col {col} missing component name')\n        return value.strip()\n\n    def get_parameter_name(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name from work_sheet.\"\"\"\n        return self.get_parameter_name_and_description(row)[0]\n\n    def get_parameter_name_and_description(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name and description from work_sheet.\"\"\"\n        name = None\n        description = None\n        col = self._get_column_letter(self._column.rename_parameter_opt_parm)\n        combined_values = self._work_sheet[col + str(row)].value\n        if combined_values is not None:\n            if '\\n' in combined_values:\n                parameter_parts = combined_values.split('\\n')\n            elif ' ' in combined_values:\n                parameter_parts = combined_values.split(' ', 1)\n            else:\n                parameter_parts = combined_values\n            if len(parameter_parts) == 2:\n                name = parameter_parts[1].strip()\n                description = parameter_parts[0].strip()\n                sname = str(name).strip()\n                name = sname.replace(' ', '_')\n                if name != sname:\n                    self._add_row(row, self.rows_invalid_parameter_name)\n            else:\n                logger.info(f'row {row} col {col} invalid value')\n        if name is None and self.get_parameter_value_default(row) is not None:\n            self._add_row(row, self.rows_missing_parameters)\n        value = name, description\n        return value\n\n    def _get_control_id(self, row: int) -> int:\n\"\"\"Get control_id from work_sheet.\"\"\"\n        col = self._get_column_letter(self._column.control_id)\n        value = self._work_sheet[col + str(row)].value\n        return value\n\n    def _get_column_letter(self, name: str) -> str:\n\"\"\"Get column letter.\"\"\"\n        value = self.map_name_to_letters[name]\n        if len(value) == 1:\n            value = value[0]\n        return value\n\n    def _map_columns(self) -> None:\n\"\"\"Map columns.\"\"\"\n        self.map_name_to_letters = {}\n        columns = self._work_sheet.max_column\n        for column in range(1, columns + 1):\n            cell_value = self._cell_value(1, column)\n            if cell_value is None:\n                continue\n            cell_tokens = cell_value.split()\n            normalized_cell_value = ' '.join(cell_tokens)\n            # find columns of interest\n            if self._column.control_id in cell_tokens:\n                self._add_column(self._column.control_id, column, 1)\n            elif self._column.control_text in cell_tokens:\n                self._add_column(self._column.control_text, column, 1)\n            elif self._column.goal_name_id in cell_tokens:\n                self._add_column(self._column.goal_name_id, column, 1)\n            elif self._column.goal_version in cell_tokens:\n                self._add_column(self._column.goal_version, column, 1)\n            elif self._column.rule_name_id in cell_tokens:\n                self._add_column(self._column.rule_name_id, column, 1)\n            elif self._column.rule_version in cell_tokens:\n                self._add_column(self._column.rule_version, column, 1)\n            # parameters and alternatives (exact tokens match)\n            elif cell_tokens == self._column.tokens_parameter_opt_parm:\n                self._add_column(self._column.rename_parameter_opt_parm, column, 1)\n            elif cell_tokens == self._column.tokens_values_alternatives:\n                self._add_column(self._column.rename_values_alternatives, column, 1)\n            # filter column (exact string match)\n            elif self._column.filter_column == normalized_cell_value:\n                self._add_column(self._column.filter_column, column, 1)\n            # nist mappings and resource title (multiple columns match)\n            elif is_ordered_sublist(self._column.tokens_nist_mappings, cell_tokens):\n                self._add_column(self._column.nist_mappings, column, 0)\n            elif self._column.resource_title in cell_tokens:\n                self._add_column(self._column.resource_title, column, 0)\n        # insure expected columns found\n        for name in [self._column.control_id,\n                     self._column.control_text,\n                     self._column.rule_name_id,\n                     self._column.rule_version,\n                     self._column.goal_name_id,\n                     self._column.goal_version,\n                     self._column.nist_mappings,\n                     self._column.resource_title,\n                     self._column.rename_parameter_opt_parm,\n                     self._column.rename_values_alternatives]:\n            if name not in self.map_name_to_letters.keys():\n                raise RuntimeError(f'missing column {name}')\n\n    def _add_column(self, name: str, column: int, limit: int) -> None:\n\"\"\"Add column.\"\"\"\n        if name not in self.map_name_to_letters:\n            self.map_name_to_letters[name] = []\n        if limit > 0 and len(self.map_name_to_letters[name]) == limit:\n            raise RuntimeError(f'duplicate column {name} {get_column_letter(column)}')\n        self.map_name_to_letters[name].append(get_column_letter(column))\n\n    def _cell_value(self, row: int, col: int) -> Any:\n\"\"\"Get value for cell, adjusting for merged cells.\"\"\"\n        cell = self._work_sheet.cell(row, col)\n        retval = cell.value\n        if isinstance(cell, MergedCell):\n            # cell is merged\n            for mc_range in self._work_sheet.merged_cells.ranges:\n                coord = get_column_letter(col) + str(row)\n                if coord in mc_range:\n                    retval = mc_range.start_cell.value\n        return retval\n\n    def _normalize_control(self, control: str) -> Tuple[str, List[str]]:\n\"\"\"Remove parenthesized characters from controls.\"\"\"\n        statements = []\n        for i in string.ascii_lowercase:\n            needle = '(' + i + ')'\n            if needle in control:\n                statements.append(needle)\n                control = control.replace(needle, '')\n        control = control.lower()\n        return control, statements\n\n    def _add_row(self, row: int, account: List[int]) -> None:\n\"\"\"Add row to accounting list of rows.\"\"\"\n        if row not in account:\n            account.append(row)\n\n    def report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n        if self.rows_missing_control_id:\n            logger.info(f'rows missing control_id: {self.rows_missing_control_id}')\n        if self.rows_invalid_goal_name_id:\n            logger.info(f'rows invalid goal_name_id: {self.rows_invalid_goal_name_id}')\n        if self.rows_missing_rule_name_id:\n            logger.info(f'rows missing rule_name_id: {self.rows_missing_rule_name_id}')\n        if self.rows_invalid_rule_name_id:\n            logger.info(f'rows invalid rule_name_id: {self.rows_invalid_rule_name_id}')\n        if self.rows_invalid_parameter_name:\n            logger.info(f'rows invalid parameter_name: {self.rows_invalid_parameter_name}')\n        if self.rows_missing_controls:\n            logger.info(f'rows missing controls: {self.rows_missing_controls}')\n        if self.rows_missing_parameters:\n            logger.info(f'rows missing parameters: {self.rows_missing_parameters}')\n        if self.rows_missing_parameters_values:\n            logger.info(f'rows missing parameters values: {self.rows_missing_parameters_values}')\n        if self.rows_filtered:\n            logger.info(f'rows filtered: {self.rows_filtered}')\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_check","title":"by_check","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_control","title":"by_control","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_goal","title":"by_goal","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.by_rule","title":"by_rule","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.profile_type","title":"profile_type: str property readonly","text":"

                                                                            Profile type.

                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.profile_types","title":"profile_types","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.__init__","title":"__init__(self) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._column = Column()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.configure","title":"configure(self, task)","text":"

                                                                            Configure.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def configure(self, task: TaskBase) -> bool:\n\"\"\"Configure.\"\"\"\n    if not task._config:\n        logger.warning('config missing')\n        return False\n    # config verbosity\n    quiet = task._config.get('quiet', False)\n    task._verbose = not quiet\n    # required for component-definition\n    if not self.configure_cd(task):\n        return False\n    # required for profile\n    if not self.configure_profile(task):\n        return False\n    # optional\n    self._column.filter_column = task._config.get('filter-column', None)\n    # config spread sheet\n    spread_sheet = task._config.get('spread-sheet-file')\n    if spread_sheet is None:\n        logger.warning('config missing \"spread-sheet\"')\n        return False\n    if not pathlib.Path(spread_sheet).exists():\n        logger.warning('\"spread-sheet\" not found')\n        return False\n    sheet_name = task._config.get('work-sheet-name')\n    if sheet_name is None:\n        logger.warning('config missing \"work-sheet-name\"')\n        return False\n    # announce spreadsheet\n    if task._verbose:\n        logger.info(f'input: {spread_sheet}')\n    # get profile type\n    if task.name == 'xlsx-to-oscal-profile':\n        self._profile_type = task._config.get('profile-type', self.profile_types[0])\n        if self._profile_type not in self.profile_types:\n            logger.warning(f'invalid \"profile-type\" {self._profile_type} ')\n            return False\n    else:\n        self._profile_type = None\n    # load spread sheet\n    self.load(spread_sheet, sheet_name)\n    return True\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.configure_cd","title":"configure_cd(self, task)","text":"

                                                                            Configure cd.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def configure_cd(self, task: TaskBase) -> bool:\n\"\"\"Configure cd.\"\"\"\n    if task.name == 'xlsx-to-oscal-cd':\n        catalog_file = task._config.get('catalog-file')\n        if catalog_file is None:\n            logger.warning('config missing \"catalog-file\"')\n            return False\n        try:\n            catalog = Catalog.oscal_read(pathlib.Path(catalog_file))\n            logger.debug(f'catalog: {catalog_file}')\n        except Exception as e:  # pragma: no cover\n            raise TrestleError(f'Error loading catalog {catalog_file}: {e}')\n        task.catalog_interface = CatalogInterface(catalog)\n    return True\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.configure_profile","title":"configure_profile(self, task)","text":"

                                                                            Configure profile.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def configure_profile(self, task: TaskBase) -> bool:\n\"\"\"Configure profile.\"\"\"\n    if task.name == 'xlsx-to-oscal-profile':\n        profile_title = task._config.get('profile-title')\n        if profile_title is None:\n            logger.warning('config missing \"profile-title\"')\n            return False\n        spread_sheet_url = task._config.get('spread-sheet-url')\n        if spread_sheet_url is None:\n            logger.warning('config missing \"spread-sheet-url\"')\n            return False\n    return True\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_check_name_id","title":"get_check_name_id(self, row, strict=False)","text":"

                                                                            Get check_name_id from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_check_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get check_name_id from work_sheet.\"\"\"\n    return self.get_goal_name_id(row, strict)\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_component_name","title":"get_component_name(self, row)","text":"

                                                                            Get component_name from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_component_name(self, row: int) -> str:\n\"\"\"Get component_name from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.resource_title)\n    value = self._work_sheet[col + str(row)].value\n    if value is None:\n        raise RuntimeError(f'row {row} col {col} missing component name')\n    return value.strip()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_controls","title":"get_controls(self, row)","text":"

                                                                            Produce dict of controls mapped to statements.

                                                                            Example: {'au-2': ['(a)', '(d)'], 'au-12': [], 'si-4': ['(a)', '(b)', '(c)']}

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_controls(self, row: int) -> Dict[str, List[str]]:\n\"\"\"Produce dict of controls mapped to statements.\n\n    Example: {'au-2': ['(a)', '(d)'], 'au-12': [], 'si-4': ['(a)', '(b)', '(c)']}\n    \"\"\"\n    value = {}\n    for col in self._get_column_letter(self._column.nist_mappings):\n        control = self._work_sheet[col + str(row)].value\n        if control is None:\n            continue\n        # remove blanks\n        control = ''.join(control.split())\n        if len(control) < 1 or control.lower() == 'none':\n            continue\n        # remove rhs of : inclusive\n        if ':' in control:\n            control = control.split(':')[0]\n        # remove alphabet parts of control & accumulate in statements\n        control, statements = self._normalize_control(control)\n        # skip bogus control made up if dashes only\n        if len(control.replace('-', '')) == 0:\n            continue\n        if control not in value.keys():\n            value[control] = statements\n    if len(value.keys()) == 0:\n        self._add_row(row, self.rows_missing_controls)\n    logger.debug(f'row: {row} controls {value}')\n    return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_goal_name_id","title":"get_goal_name_id(self, row, strict=True)","text":"

                                                                            Get goal_name_id from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_goal_name_id(self, row: int, strict: bool = True) -> str:\n\"\"\"Get goal_name_id from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.goal_name_id)\n    value = self._work_sheet[col + str(row)].value\n    if value is None:\n        self._add_row(row, self.rows_missing_goal_name_id)\n    else:\n        value = str(value).strip()\n        if strict:\n            svalue = str(value).strip()\n            value = ''.join(str(svalue).split())\n            if value != svalue:\n                self._add_row(row, self.rows_invalid_goal_name_id)\n    return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_goal_remarks","title":"get_goal_remarks(self, row)","text":"

                                                                            Get goal_remarks from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_goal_remarks(self, row: int) -> str:\n\"\"\"Get goal_remarks from work_sheet.\"\"\"\n    tokens = self._get_goal_text_tokens(row)\n    # replace \"Check whether\" with \"Ensure\", if present\n    if tokens:\n        if tokens[0] == 'Check':\n            if len(tokens) > 1:\n                if tokens[1] == 'whether':\n                    tokens.pop(0)\n            tokens[0] = 'Ensure'\n    value = ' '.join(tokens)\n    return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_name","title":"get_parameter_name(self, row)","text":"

                                                                            Get parameter_name from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_parameter_name(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name from work_sheet.\"\"\"\n    return self.get_parameter_name_and_description(row)[0]\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_name_and_description","title":"get_parameter_name_and_description(self, row)","text":"

                                                                            Get parameter_name and description from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_parameter_name_and_description(self, row: int) -> Tuple[str, str]:\n\"\"\"Get parameter_name and description from work_sheet.\"\"\"\n    name = None\n    description = None\n    col = self._get_column_letter(self._column.rename_parameter_opt_parm)\n    combined_values = self._work_sheet[col + str(row)].value\n    if combined_values is not None:\n        if '\\n' in combined_values:\n            parameter_parts = combined_values.split('\\n')\n        elif ' ' in combined_values:\n            parameter_parts = combined_values.split(' ', 1)\n        else:\n            parameter_parts = combined_values\n        if len(parameter_parts) == 2:\n            name = parameter_parts[1].strip()\n            description = parameter_parts[0].strip()\n            sname = str(name).strip()\n            name = sname.replace(' ', '_')\n            if name != sname:\n                self._add_row(row, self.rows_invalid_parameter_name)\n        else:\n            logger.info(f'row {row} col {col} invalid value')\n    if name is None and self.get_parameter_value_default(row) is not None:\n        self._add_row(row, self.rows_missing_parameters)\n    value = name, description\n    return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_usage","title":"get_parameter_usage(self, row)","text":"

                                                                            Get parameter_usage from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_parameter_usage(self, row: int) -> str:\n\"\"\"Get parameter_usage from work_sheet.\"\"\"\n    return self.get_goal_remarks(row)\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_value_default","title":"get_parameter_value_default(self, row)","text":"

                                                                            Get parameter_value_default from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_parameter_value_default(self, row: int) -> str:\n\"\"\"Get parameter_value_default from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.rename_values_alternatives)\n    value = self._work_sheet[col + str(row)].value\n    if value is not None:\n        value = str(value).split(',')[0].strip()\n    return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_parameter_values","title":"get_parameter_values(self, row)","text":"

                                                                            Get parameter_values from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_parameter_values(self, row: int) -> str:\n\"\"\"Get parameter_values from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.rename_values_alternatives)\n    value = self._work_sheet[col + str(row)].value\n    if value is None and self.get_parameter_name(row) is not None:\n        self._add_row(row, self.rows_missing_parameters_values)\n    # massage into comma separated list of values\n    else:\n        value = str(value).strip().replace(' ', '')\n        value = value.replace(',[]', '')\n        value = value.replace('[', '')\n        value = value.replace(']', '')\n        value = value.split(',')\n    return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.get_rule_name_id","title":"get_rule_name_id(self, row, strict=False)","text":"

                                                                            Get rule_name_id from work_sheet.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_rule_name_id(self, row: int, strict: bool = False) -> str:\n\"\"\"Get rule_name_id from work_sheet.\"\"\"\n    col = self._get_column_letter(self._column.rule_name_id)\n    value = self._work_sheet[col + str(row)].value\n    if value is None:\n        self._add_row(row, self.rows_missing_rule_name_id)\n    else:\n        value = str(value).strip()\n        if strict:\n            svalue = str(value).strip()\n            value = ''.join(str(svalue).split())\n            if value != svalue:\n                self._add_row(row, self.rows_invalid_rule_name_id)\n    return value\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.load","title":"load(self, spread_sheet, sheet_name)","text":"

                                                                            Load.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def load(self, spread_sheet: str, sheet_name: str) -> None:\n\"\"\"Load.\"\"\"\n    self._spread_sheet = spread_sheet\n    self._sheet_name = sheet_name\n    self._wb = load_workbook(self._spread_sheet)\n    self._work_sheet = self._wb[self._sheet_name]\n    self._map_name_to_letters = {}\n    # accumulators\n    self.rows_missing_control_id = []\n    self.rows_missing_goal_name_id = []\n    self.rows_invalid_goal_name_id = []\n    self.rows_missing_rule_name_id = []\n    self.rows_invalid_rule_name_id = []\n    self.rows_invalid_parameter_name = []\n    self.rows_missing_controls = []\n    self.rows_missing_parameters = []\n    self.rows_missing_parameters_values = []\n    self.rows_filtered = []\n    # map columns\n    self._map_columns()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.print_info","title":"print_info(self, name, oscal_name)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def print_info(self, name, oscal_name) -> None:\n\"\"\"Print the help string.\"\"\"\n    logger.info(f'Help information for {name} task.')\n    logger.info('')\n    logger.info(f'Purpose: From spread sheet and catalog produce OSCAL {oscal_name} file.')\n    logger.info('')\n    logger.info(f'Configuration flags sit under [task.{name}]:')\n    if oscal_name == 'component_definition':\n        text1 = '  catalog-file      = '\n        text2 = '(required) the path of the OSCAL catalog file.'\n        logger.info(text1 + text2)\n    text1 = '  spread-sheet-file = '\n    text2 = '(required) the path of the spread sheet file.'\n    logger.info(text1 + text2)\n    text1 = '  work-sheet-name   = '\n    text2 = '(required) the name of the work sheet in the spread sheet file.'\n    logger.info(text1 + text2)\n    for line in self._column.help_list:\n        logger.info(line)\n    text1 = '  output-dir        = '\n    text2 = '(required) the path of the output directory for synthesized OSCAL .json files.'\n    logger.info(text1 + text2)\n    text1 = '  output-overwrite  = '\n    text2 = '(optional) true [default] or false; replace existing output when true.'\n    logger.info(text1 + text2)\n    text1 = '  filter-column     = '\n    text2 = '(optional) column heading of yes/no values; process only \"yes\" rows.'\n    logger.info(text1 + text2)\n    text1 = '  profile-type      = '\n    text2 = f'(optional) one of {self.profile_types}'\n    logger.info(text1 + text2)\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.report_issues","title":"report_issues(self)","text":"

                                                                            Report issues.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n    if self.rows_missing_control_id:\n        logger.info(f'rows missing control_id: {self.rows_missing_control_id}')\n    if self.rows_invalid_goal_name_id:\n        logger.info(f'rows invalid goal_name_id: {self.rows_invalid_goal_name_id}')\n    if self.rows_missing_rule_name_id:\n        logger.info(f'rows missing rule_name_id: {self.rows_missing_rule_name_id}')\n    if self.rows_invalid_rule_name_id:\n        logger.info(f'rows invalid rule_name_id: {self.rows_invalid_rule_name_id}')\n    if self.rows_invalid_parameter_name:\n        logger.info(f'rows invalid parameter_name: {self.rows_invalid_parameter_name}')\n    if self.rows_missing_controls:\n        logger.info(f'rows missing controls: {self.rows_missing_controls}')\n    if self.rows_missing_parameters:\n        logger.info(f'rows missing parameters: {self.rows_missing_parameters}')\n    if self.rows_missing_parameters_values:\n        logger.info(f'rows missing parameters values: {self.rows_missing_parameters_values}')\n    if self.rows_filtered:\n        logger.info(f'rows filtered: {self.rows_filtered}')\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.XlsxHelper.row_generator","title":"row_generator(self)","text":"

                                                                            Generate rows until control_id is None.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def row_generator(self) -> Iterator[int]:\n\"\"\"Generate rows until control_id is None.\"\"\"\n    row = 1\n    rows_skipped_consecutive = 0\n    # assume no more data when 100 consecutve rows no control id\n    rows_skipped_consecutive_limit = 100\n    while True:\n        row = row + 1\n        control_id = self._get_control_id(row)\n        goal_id = self.get_goal_name_id(row)\n        if control_id is None and goal_id is None:\n            rows_skipped_consecutive += 1\n            if rows_skipped_consecutive < rows_skipped_consecutive_limit:\n                continue\n            logger.debug(f'break: {row} {rows_skipped_consecutive}')\n            break\n        if control_id is None:\n            self._add_row(row, self.rows_missing_control_id)\n            continue\n        if goal_id is None:\n            self._add_row(row, self.rows_missing_goal_name_id)\n            continue\n        if self._is_filtered(row):\n            continue\n        yield row\n        rows_skipped_consecutive = 0\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper-functions","title":"Functions","text":""},{"location":"api_reference/trestle.tasks.xlsx_helper/#trestle.tasks.xlsx_helper.get_trestle_version","title":"get_trestle_version()","text":"

                                                                            Get trestle version wrapper.

                                                                            Source code in trestle/tasks/xlsx_helper.py
                                                                            def get_trestle_version() -> str:\n\"\"\"Get trestle version wrapper.\"\"\"\n    return __version__\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/","title":"xlsx_to_oscal_cd","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd","title":"trestle.tasks.xlsx_to_oscal_cd","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.key_sep","title":"key_sep","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.sep","title":"sep","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition","title":" XlsxToOscalComponentDefinition (TaskBase) ","text":"

                                                                            Task to create OSCAL ComponentDefinition json.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                                                            class XlsxToOscalComponentDefinition(TaskBase):\n\"\"\"\n    Task to create OSCAL ComponentDefinition json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'xlsx-to-oscal-cd'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task xlsx-to-oscal-cd.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self.xlsx_helper = XlsxHelper()\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n        self._timestamp = timestamp\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        self.xlsx_helper.print_info(self.name, 'component_definition')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Execute path core.\"\"\"\n        if not self.xlsx_helper.configure(self):\n            return TaskOutcome('failure')\n        # config output\n        odir = self._config.get('output-dir')\n        opth = pathlib.Path(odir)\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'component-definition.json'\n        ofile = opth / oname\n        if not self._overwrite and pathlib.Path(ofile).exists():\n            logger.warning(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # initialize\n        self.defined_components = {}\n        # roles, responsible_roles, parties, responsible parties\n        party_uuid_01 = str(uuid.uuid4())\n        party_uuid_02 = str(uuid.uuid4())\n        party_uuid_03 = str(uuid.uuid4())\n        roles = self._build_roles()\n        responsible_roles = self._build_responsible_roles(party_uuid_01, party_uuid_02, party_uuid_03)\n        parties = self._build_parties(party_uuid_01, party_uuid_02, party_uuid_03)\n        responsible_parties = self._build_responsible_parties(party_uuid_01, party_uuid_02, party_uuid_03)\n        # process each row of spread sheet\n        self._process_rows(responsible_roles)\n        # create OSCAL ComponentDefinition\n        metadata = Metadata(\n            title='Component definition for ' + self._get_catalog_title() + ' profiles',\n            last_modified=self._timestamp,\n            oscal_version=OSCAL_VERSION,\n            version=get_trestle_version(),\n            roles=roles,\n            parties=parties,\n            responsible_parties=responsible_parties\n        )\n        component_definition = ComponentDefinition(\n            uuid=str(uuid.uuid4()),\n            metadata=metadata,\n            components=list(self.defined_components.values()),\n        )\n        # write OSCAL ComponentDefinition to file\n        if self._verbose:\n            logger.info(f'output: {ofile}')\n        component_definition.oscal_write(pathlib.Path(ofile))\n        # issues\n        self._report_issues()\n        return TaskOutcome('success')\n\n    def _process_rows(self, responsible_roles: List[ResponsibleRole]) -> None:\n\"\"\"Process spread sheet rows.\"\"\"\n        ci_map = {}\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            goal_name_id = self.xlsx_helper.get_goal_name_id(row)\n            controls = self.xlsx_helper.get_controls(row)\n            if len(controls.keys()) == 0:\n                continue\n            # component\n            component_name = self.xlsx_helper.get_component_name(row)\n            component_type = 'Service'\n            defined_component = self._get_defined_component(component_name, component_type)\n            # parameter\n            parameter_name, parameter_description = self.xlsx_helper.get_parameter_name_and_description(row)\n            # control implementations\n            source = self._get_catalog_url()\n            description = component_name + ' implemented controls for ' + self._get_catalog_title(\n            ) + '. It includes assessment asset configuration for CICD.'\n            key = source + key_sep + description\n            control_implementation = ci_map.get(key)\n            if not control_implementation:\n                ci_map[key] = ControlImplementation(\n                    uuid=str(uuid.uuid4()),\n                    source=source,\n                    description=description,\n                    implemented_requirements=[],\n                )\n                control_implementation = ci_map[key]\n                if defined_component.control_implementations is None:\n                    defined_component.control_implementations = []\n                defined_component.control_implementations.append(control_implementation)\n            # implemented requirements\n            self._add_implemented_requirements(\n                row, control_implementation, controls, component_name, parameter_name, responsible_roles, goal_name_id\n            )\n            # keep alternative parameter values at control implementation level\n            parameter_values = self.xlsx_helper.get_parameter_values(row)\n            self._add_set_parameter_values(parameter_name, parameter_values, control_implementation)\n\n    def _add_implemented_requirements(\n        self,\n        row: int,\n        control_implementation: ControlImplementation,\n        controls: Dict[str, List[str]],\n        component_name: str,\n        parameter_name: str,\n        responsible_roles: List[ResponsibleRole],\n        goal_name_id: str\n    ) -> None:\n\"\"\"Add implemented requirements.\"\"\"\n        goal_remarks = self.xlsx_helper.get_goal_remarks(row)\n        parameter_value_default = self.xlsx_helper.get_parameter_value_default(row)\n        for control in controls.keys():\n            control_uuid = str(uuid.uuid4())\n            prop1 = Property(\n                name='goal_name_id',\n                class_=self._get_class_for_property_name('goal_name_id'),\n                value=goal_name_id,\n                ns=self._get_namespace(),\n                remarks=str(goal_remarks)\n            )\n            prop2 = Property(\n                name='goal_version',\n                class_=self._get_class_for_property_name('goal_version'),\n                value=self._get_goal_version(),\n                ns=self._get_namespace(),\n                remarks=str(goal_name_id)\n            )\n            props = [prop1, prop2]\n            control_id, _ = self.catalog_interface.get_control_id_and_status(control)\n            if not control_id:\n                logger.info(f'row {row} control {control} not found in catalog')\n                control_id = control\n            # implemented_requirement\n            implemented_requirement = ImplementedRequirement(\n                uuid=control_uuid,\n                description=control,\n                props=props,\n                control_id=control_id,\n                responsible_roles=responsible_roles,\n            )\n            # add statements\n            self._add_statements(row, control, controls, component_name, implemented_requirement)\n            # add set_parameter\n            self._add_set_parameter_default(parameter_name, parameter_value_default, implemented_requirement)\n            # implemented_requirements\n            control_implementation.implemented_requirements.append(implemented_requirement)\n\n    def _add_statements(\n        self,\n        row: int,\n        control: str,\n        controls: Dict[str, List[str]],\n        component_name: str,\n        implemented_requirement: ImplementedRequirement\n    ) -> None:\n\"\"\"Add statements.\"\"\"\n        control_statements = controls[control]\n        if control_statements:\n            statements = []\n            for control_statement in control_statements:\n                statement_id = control + control_statement\n                if any(i in control for i in '()'):\n                    control = control.replace('(', '_')\n                    control = control.replace(')', '')\n                    logger.info(f'row {row} control {control} edited to remove parentheses')\n                statement = Statement(\n                    statement_id=control,\n                    uuid=str(uuid.uuid4()),\n                    description=f'{component_name} implements {statement_id}'\n                )\n                statements.append(statement)\n            implemented_requirement.statements = statements\n\n    def _add_set_parameter_values(\n        self, parameter_name: str, parameter_values: str, control_implementation: ControlImplementation\n    ) -> None:\n\"\"\"Add set parameter values (the set of choices).\"\"\"\n        if parameter_name is not None:\n            parameter_name = parameter_name.replace(' ', '_')\n            if parameter_values is not None:\n                set_parameters = [SetParameter(param_id=parameter_name, values=parameter_values)]\n                if control_implementation.set_parameters is None:\n                    control_implementation.set_parameters = []\n                # set_parameters is a list\n                control_implementation.set_parameters.extend(set_parameters)\n\n    def _add_set_parameter_default(\n        self, parameter_name: str, parameter_value_default: str, implemented_requirement: ImplementedRequirement\n    ) -> None:\n\"\"\"Add set parameter default (the \"recommended\" value).\"\"\"\n        if parameter_name is not None:\n            parameter_name = parameter_name.replace(' ', '_')\n            if parameter_value_default is not None:\n                if implemented_requirement.set_parameters is None:\n                    implemented_requirement.set_parameters = []\n                values = [parameter_value_default]\n                set_parameter = SetParameter(param_id=parameter_name, values=values)\n                set_parameters = [set_parameter]\n                # set_parameters is a list\n                implemented_requirement.set_parameters.extend(set_parameters)\n\n    def _get_defined_component(self, component_name: str, component_type: str) -> DefinedComponent:\n\"\"\"Get defined component.\"\"\"\n        key = component_name + key_sep + component_type\n        defined_component = self.defined_components.get(key)\n        if not defined_component:\n            # create new component\n            component_title = component_name\n            component_description = component_name\n            defined_component = DefinedComponent(\n                uuid=str(uuid.uuid4()),\n                description=component_description,\n                title=component_title,\n                type=component_type,\n            )\n            self.defined_components[key] = defined_component\n        return defined_component\n\n    def _build_roles(self) -> List[Role]:\n\"\"\"Build roles.\"\"\"\n        value = [\n            Role(id='prepared-by', title='Indicates the organization that created this content.'),\n            Role(id='prepared-for', title='Indicates the organization for which this content was created..'),\n            Role(\n                id='content-approver',\n                title='Indicates the organization responsible for all content represented in the \"document\".'\n            ),\n        ]\n        return value\n\n    def _build_responsible_roles(self, party_uuid_01: str, party_uuid_02: str,\n                                 party_uuid_03: str) -> List[ResponsibleRole]:\n\"\"\"Build responsible roles.\"\"\"\n        role_prepared_by = ResponsibleRole(role_id='prepared-by', party_uuids=[party_uuid_01])\n        role_prepared_for = ResponsibleRole(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        role_content_approver = ResponsibleRole(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            role_prepared_by,\n            role_prepared_for,\n            role_content_approver,\n        ]\n        return value\n\n    def _build_parties(self, party_uuid_01: str, party_uuid_02: str, party_uuid_03: str) -> List[Party]:\n\"\"\"Build parties.\"\"\"\n        value = [\n            Party(uuid=party_uuid_01, type='organization', name=self._get_org_name(), remarks=self._get_org_remarks()),\n            Party(\n                uuid=party_uuid_02,\n                type='organization',\n                name='Customer',\n                remarks='organization to be customized at account creation only for their Component Definition'\n            ),\n            Party(\n                uuid=party_uuid_03,\n                type='organization',\n                name='ISV',\n                remarks='organization to be customized at ISV subscription only for their Component Definition'\n            ),\n        ]\n        return value\n\n    def _build_responsible_parties(self, party_uuid_01: str, party_uuid_02: str,\n                                   party_uuid_03: str) -> List[ResponsibleParty]:\n\"\"\"Build responsible parties.\"\"\"\n        prepared_by = ResponsibleParty(role_id='prepared-by', party_uuids=[party_uuid_01])\n        prepared_for = ResponsibleParty(role_id='prepared-for', party_uuids=[party_uuid_02, party_uuid_03])\n        content_approver = ResponsibleParty(role_id='content-approver', party_uuids=[party_uuid_01])\n        value = [\n            prepared_by,\n            prepared_for,\n            content_approver,\n        ]\n        return value\n\n    def _report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n        self.xlsx_helper.report_issues()\n\n    def _get_org_name(self) -> str:\n\"\"\"Get org-name from config.\"\"\"\n        value = self._config.get('org-name')\n        logger.debug(f'org-name: {value}')\n        return value\n\n    def _get_org_remarks(self) -> str:\n\"\"\"Get org-remarks from config.\"\"\"\n        value = self._config.get('org-remarks')\n        logger.debug(f'org-remarks: {value}')\n        return value\n\n    def _get_class_for_property_name(self, property_name: str) -> str:\n\"\"\"Get class for property-name from config.\"\"\"\n        value = None\n        data = self._config.get('property-name-to-class')\n        if data is not None:\n            for item in data.split(','):\n                item = item.strip()\n                parts = item.split(':')\n                if len(parts) != 2 or parts[0] != property_name:\n                    continue\n                value = parts[1]\n                break\n        logger.debug(f'property-name-to-class: {property_name} -> {value}')\n        return value\n\n    def _get_namespace(self) -> str:\n\"\"\"Get namespace from config.\"\"\"\n        value = self._config.get('namespace')\n        logger.debug(f'namespace: {value}')\n        return value\n\n    def _get_catalog_url(self) -> str:\n\"\"\"Get catalog url from config.\"\"\"\n        value = self._config.get('catalog-url')\n        logger.debug(f'catalog-url: {value}')\n        return value\n\n    def _get_catalog_title(self) -> str:\n\"\"\"Get catalog title from config.\"\"\"\n        value = self._config.get('catalog-title')\n        logger.debug(f'catalog-title: {value}')\n        return value\n\n    def _get_goal_version(self) -> str:\n\"\"\"Fix goal_version at 1.0.\"\"\"\n        return '1.0'\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task xlsx-to-oscal-cd.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task xlsx-to-oscal-cd.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self.xlsx_helper = XlsxHelper()\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.execute","title":"execute(self)","text":"

                                                                            Provide an executed outcome.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    self.xlsx_helper.print_info(self.name, 'component_definition')\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.set_timestamp","title":"set_timestamp(self, timestamp)","text":"

                                                                            Set the timestamp.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                                                            def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n    self._timestamp = timestamp\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_cd/#trestle.tasks.xlsx_to_oscal_cd.XlsxToOscalComponentDefinition.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_cd.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/","title":"xlsx_to_oscal_profile","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile","title":"trestle.tasks.xlsx_to_oscal_profile","text":"

                                                                            OSCAL transformation tasks.

                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.logger","title":"logger","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile-classes","title":"Classes","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile","title":" XlsxToOscalProfile (TaskBase) ","text":"

                                                                            Task to create OSCAL Profile json.

                                                                            Attributes:

                                                                            Name Type Description name str

                                                                            Name of the task.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                                                            class XlsxToOscalProfile(TaskBase):\n\"\"\"\n    Task to create OSCAL Profile json.\n\n    Attributes:\n        name: Name of the task.\n    \"\"\"\n\n    name = 'xlsx-to-oscal-profile'\n\n    def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n        Initialize trestle task xlsx-to-oscal-profile.\n\n        Args:\n            config_object: Config section associated with the task.\n        \"\"\"\n        super().__init__(config_object)\n        self.xlsx_helper = XlsxHelper()\n        self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                    ).isoformat()\n\n    def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n        self._timestamp = timestamp\n\n    def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n        self.xlsx_helper.print_info(self.name, 'profile')\n\n    def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n        return TaskOutcome('simulated-success')\n\n    def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n        try:\n            return self._execute()\n        except Exception:\n            logger.info(traceback.format_exc())\n            return TaskOutcome('failure')\n\n    def _execute(self) -> TaskOutcome:\n\"\"\"Execute path core.\"\"\"\n        if not self.xlsx_helper.configure(self):\n            return TaskOutcome('failure')\n        # config output\n        odir = self._config.get('output-dir')\n        opth = pathlib.Path(odir)\n        self._overwrite = self._config.getboolean('output-overwrite', True)\n        # insure output dir exists\n        opth.mkdir(exist_ok=True, parents=True)\n        # calculate output file name & check writability\n        oname = 'profile.json'\n        ofile = opth / oname\n        if not self._overwrite and pathlib.Path(ofile).exists():\n            logger.error(f'output: {ofile} already exists')\n            return TaskOutcome('failure')\n        # create OSCAL Profile\n        metadata = Metadata(\n            title='Profile for ' + self._get_profile_title(),\n            last_modified=self._timestamp,\n            oscal_version=OSCAL_VERSION,\n            version=get_trestle_version(),\n        )\n        if self.xlsx_helper.profile_type == self.xlsx_helper.by_control:\n            imports = self._get_imports_by_control()\n            profile = Profile(\n                uuid=str(uuid.uuid4()),\n                metadata=metadata,\n                imports=imports,\n            )\n        else:\n            if self.xlsx_helper.profile_type == self.xlsx_helper.by_rule:\n                imports = self._get_imports_by_rule()\n            elif self.xlsx_helper.profile_type == self.xlsx_helper.by_check:\n                imports = self._get_imports_by_check()\n            else:\n                imports = self._get_imports_by_goal()\n            set_parameters = self._get_set_parameters()\n            modify = Modify(set_parameters=set_parameters)\n            profile = Profile(\n                uuid=str(uuid.uuid4()),\n                metadata=metadata,\n                imports=imports,\n                modify=modify,\n            )\n        # write OSCAL Profile to file\n        if self._verbose:\n            logger.info(f'output: {ofile}')\n        profile.oscal_write(pathlib.Path(ofile))\n        # issues\n        self._report_issues()\n        return TaskOutcome('success')\n\n    def _get_imports_by_goal(self) -> List[Import]:\n\"\"\"Get imports by goal.\"\"\"\n        return self._get_imports_by_check()\n\n    def _get_imports_by_control(self) -> List[Import]:\n\"\"\"Get imports by control.\"\"\"\n        import_ = Import(\n            href=self._get_spread_sheet_url(),\n            include_controls=[SelectControlById(with_ids=self._get_with_ids_by_control())],\n        )\n        imports = [import_]\n        return imports\n\n    def _get_imports_by_rule(self) -> List[Import]:\n\"\"\"Get imports by rule.\"\"\"\n        import_ = Import(\n            href=self._get_spread_sheet_url(),\n            include_controls=[SelectControlById(with_ids=self._get_with_ids_by_rule())],\n        )\n        imports = [import_]\n        return imports\n\n    def _get_imports_by_check(self) -> List[Import]:\n\"\"\"Get imports by check.\"\"\"\n        import_ = Import(\n            href=self._get_spread_sheet_url(),\n            include_controls=[SelectControlById(with_ids=self._get_with_ids_by_check())],\n        )\n        imports = [import_]\n        return imports\n\n    def _get_with_ids_by_control(self) -> List[str]:\n\"\"\"Get controls from spread sheet.\"\"\"\n        control_list = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            controls = self.xlsx_helper.get_controls(row)\n            if controls is not None:\n                for control in controls:\n                    control = self._oscal_namify(control)\n                    if control in control_list:\n                        continue\n                    control_list.append(control)\n        return sorted(control_list, key=self._control_sort_key)\n\n    def _get_with_ids_by_rule(self) -> List[str]:\n\"\"\"Get rules from spread sheet.\"\"\"\n        rule_name_id_list = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            rule_name_id = self.xlsx_helper.get_rule_name_id(row, strict=True)\n            if rule_name_id is not None:\n                if rule_name_id in rule_name_id_list:\n                    continue\n                rule_name_id_list.append(rule_name_id)\n        return sorted(rule_name_id_list)\n\n    def _get_with_ids_by_check(self) -> List[str]:\n\"\"\"Get check from spread sheet.\"\"\"\n        check_name_id_list = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            check_name_id = self.xlsx_helper.get_check_name_id(row, strict=True)\n            if check_name_id is not None:\n                if check_name_id in check_name_id_list:\n                    continue\n                check_name_id_list.append(check_name_id)\n        return sorted(check_name_id_list)\n\n    def _control_sort_key(self, control: str) -> Tuple[str, int, int]:\n\"\"\"Fabricate sort key.\"\"\"\n        k1 = control.split('-')[0]\n        k2 = int(control.split('-')[1].split('.')[0])\n        if '.' in control:\n            k3 = int(control.split('-')[1].split('.')[1])\n        else:\n            k3 = 0\n        return (k1, k2, k3)\n\n    def _oscal_namify(self, control: str) -> str:\n\"\"\"Rectify parenthesized numbers in controls.\"\"\"\n        control = control.replace('(', '.')\n        control = control.replace(')', '')\n        return control\n\n    def _get_set_parameters(self) -> List[SetParameter]:\n\"\"\"Get set parameters from spread sheet.\"\"\"\n        set_parameters = []\n        for row in self.xlsx_helper.row_generator():\n            # quit when first row with no goal_id encountered\n            param_id, label = self.xlsx_helper.get_parameter_name_and_description(row)\n            usage = self.xlsx_helper.get_parameter_usage(row)\n            values = self.xlsx_helper.get_parameter_values(row)\n            if param_id is None:\n                continue\n            set_parameter = SetParameter(\n                param_id=param_id,\n                label=label,\n                usage=usage,\n            )\n            if values is not None:\n                set_parameter.values = values\n            set_parameters.append(set_parameter)\n        return set_parameters\n\n    def _get_profile_title(self) -> str:\n\"\"\"Get profile title from config.\"\"\"\n        value = self._config.get('profile-title')\n        logger.debug(f'profile-title: {value}')\n        return value\n\n    def _get_spread_sheet_url(self) -> str:\n\"\"\"Get spread sheet url from config.\"\"\"\n        value = self._config.get('spread-sheet-url')\n        logger.debug(f'spread-sheet-url: {value}')\n        return value\n\n    def _report_issues(self) -> None:\n\"\"\"Report issues.\"\"\"\n        self.xlsx_helper.report_issues()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.name","title":"name: str","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile-methods","title":"Methods","text":""},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.__init__","title":"__init__(self, config_object) special","text":"

                                                                            Initialize trestle task xlsx-to-oscal-profile.

                                                                            Parameters:

                                                                            Name Type Description Default config_object Optional[configparser.SectionProxy]

                                                                            Config section associated with the task.

                                                                            required Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                                                            def __init__(self, config_object: Optional[configparser.SectionProxy]) -> None:\n\"\"\"\n    Initialize trestle task xlsx-to-oscal-profile.\n\n    Args:\n        config_object: Config section associated with the task.\n    \"\"\"\n    super().__init__(config_object)\n    self.xlsx_helper = XlsxHelper()\n    self._timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc\n                                                                                ).isoformat()\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.execute","title":"execute(self)","text":"

                                                                            Provide an executed outcome.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                                                            def execute(self) -> TaskOutcome:\n\"\"\"Provide an executed outcome.\"\"\"\n    try:\n        return self._execute()\n    except Exception:\n        logger.info(traceback.format_exc())\n        return TaskOutcome('failure')\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.print_info","title":"print_info(self)","text":"

                                                                            Print the help string.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                                                            def print_info(self) -> None:\n\"\"\"Print the help string.\"\"\"\n    self.xlsx_helper.print_info(self.name, 'profile')\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.set_timestamp","title":"set_timestamp(self, timestamp)","text":"

                                                                            Set the timestamp.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                                                            def set_timestamp(self, timestamp: str) -> None:\n\"\"\"Set the timestamp.\"\"\"\n    self._timestamp = timestamp\n
                                                                            "},{"location":"api_reference/trestle.tasks.xlsx_to_oscal_profile/#trestle.tasks.xlsx_to_oscal_profile.XlsxToOscalProfile.simulate","title":"simulate(self)","text":"

                                                                            Provide a simulated outcome.

                                                                            Source code in trestle/tasks/xlsx_to_oscal_profile.py
                                                                            def simulate(self) -> TaskOutcome:\n\"\"\"Provide a simulated outcome.\"\"\"\n    return TaskOutcome('simulated-success')\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/","title":"osco","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco","title":"trestle.transforms.implementations.osco","text":"

                                                                            Facilitate OSCAL-OSCO transformation.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.logger","title":"logger","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer","title":" OscalProfileToOscoProfileTransformer (FromOscalTransformer) ","text":"

                                                                            Interface for Oscal Profile to Osco Profile transformer.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            class OscalProfileToOscoProfileTransformer(FromOscalTransformer):\n\"\"\"Interface for Oscal Profile to Osco Profile transformer.\"\"\"\n\n    def __init__(\n        self,\n        extends='ocp4-cis-node',\n        api_version='compliance.openshift.io/v1alpha1',\n        kind='TailoredProfile',\n        name='customized-tailored-profile',\n        namespace='openshift-compliance',\n    ) -> None:\n\"\"\"Initialize.\"\"\"\n        self._extends = extends\n        self._api_version = api_version\n        self._kind = kind\n        self._name = name\n        self._namespace = namespace\n\n    def transform(self, profile: Profile) -> str:\n\"\"\"Transform the Profile into a OSCO yaml.\"\"\"\n        self._profile = profile\n        self._osco_version = self._get_normalized_version('osco_version', '0.1.46')\n        # set values\n        set_values = self._get_set_values()\n        # spec\n        if self._osco_version < (0, 1, 40):\n            # for versions prior to 0.1.40, exclude 'description'\n            spec = {\n                'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n                'title': self._profile.metadata.title,\n                'setValues': set_values,\n            }\n        else:\n            # for versions 0.1.40 and beyond, include 'description'\n            spec = {\n                'description': self._get_metadata_prop_value('profile_mnemonic', self._name),\n                'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n                'title': self._profile.metadata.title,\n                'setValues': set_values,\n            }\n        disable_rules = self._get_disable_rules()\n        if disable_rules:\n            spec['disableRules'] = disable_rules\n        # yaml data\n        ydata = {\n            'apiVersion': self._api_version,\n            'kind': self._kind,\n            'metadata': {\n                'name': self._get_metadata_prop_value('profile_mnemonic', self._name),\n                'namespace': self._namespace,\n            },\n            'spec': spec,\n        }\n        return json.dumps(ydata)\n\n    def _get_normalized_version(self, prop_name, prop_default) -> Tuple[int, int, int]:\n\"\"\"Get normalized version.\n\n        Normalize the \"x.y.z\" string value to an integer: 1,000,000*x + 1,000*y + z.\n        \"\"\"\n        try:\n            vparts = self._get_metadata_prop_value(prop_name, prop_default).split('.')\n            normalized_version = (int(vparts[0]), int(vparts[1]), int(vparts[2]))\n        except Exception:\n            logger.warning(f'metadata prop name={prop_name} value error')\n            vparts = prop_default.split('.')\n            normalized_version = (int(vparts[0]), int(vparts[1]), int(vparts[2]))\n        return normalized_version\n\n    def _get_set_values(self) -> List[Dict]:\n\"\"\"Extract set_paramater name/value pairs from profile.\"\"\"\n        set_values = []\n        # for check versions prior to 0.1.59 include parameters\n        # for later versions parameters should not be specified, caveat emptor\n        if self._profile.modify is not None:\n            for set_parameter in as_list(self._profile.modify.set_parameters):\n                name = self._format_osco_rule_name(set_parameter.param_id)\n                parameter_value = set_parameter.values[0]\n                value = parameter_value\n                rationale = self._get_rationale_for_set_value()\n                set_value = {'name': name, 'value': value, 'rationale': rationale}\n                set_values.append(set_value)\n        return set_values\n\n    def _format_osco_rule_name(self, name: str) -> str:\n\"\"\"Format for OSCO.\n\n        1. remove prefix xccdf_org.ssgproject.content_rule_\n        2. change underscores to dashes\n        3. add prefix ocp4-\n        \"\"\"\n        normalized_name = name.replace('xccdf_org.ssgproject.content_rule_', '').replace('_', '-')\n        if not normalized_name.startswith('ocp4-'):\n            normalized_name = f'ocp4-{normalized_name}'\n        return normalized_name\n\n    def _get_metadata_prop_value(self, name: str, default_: str) -> str:\n\"\"\"Extract metadata prop or else default if not present.\"\"\"\n        for prop in as_list(self._profile.metadata.props):\n            if prop.name == name:\n                return prop.value\n        logger.info(f'using default: {name} = {default_}')\n        return default_\n\n    def _get_disable_rules(self) -> List[str]:\n\"\"\"Extract disabled rules.\"\"\"\n        value = []\n        for _import in as_list(self._profile.imports):\n            for control in as_list(_import.exclude_controls):\n                self._add_disable_rules_for_control(value, control)\n        return value\n\n    def _add_disable_rules_for_control(self, value, control):\n\"\"\"Extract disabled rules for control.\"\"\"\n        for with_id in as_list(control.with_ids):\n            name = self._format_osco_rule_name(with_id.__root__)\n            rationale = self._get_rationale_for_disable_rule()\n            entry = {'name': name, 'rationale': rationale}\n            value.append(entry)\n\n    def _get_rationale_for_set_value(self) -> str:\n\"\"\"Rationale for set value.\"\"\"\n        return 'not determinable from specification'\n\n    def _get_rationale_for_disable_rule(self) -> str:\n\"\"\"Rationale for disable rule.\"\"\"\n        return 'not determinable from specification'\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer.__init__","title":"__init__(self, extends='ocp4-cis-node', api_version='compliance.openshift.io/v1alpha1', kind='TailoredProfile', name='customized-tailored-profile', namespace='openshift-compliance') special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            def __init__(\n    self,\n    extends='ocp4-cis-node',\n    api_version='compliance.openshift.io/v1alpha1',\n    kind='TailoredProfile',\n    name='customized-tailored-profile',\n    namespace='openshift-compliance',\n) -> None:\n\"\"\"Initialize.\"\"\"\n    self._extends = extends\n    self._api_version = api_version\n    self._kind = kind\n    self._name = name\n    self._namespace = namespace\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscalProfileToOscoProfileTransformer.transform","title":"transform(self, profile)","text":"

                                                                            Transform the Profile into a OSCO yaml.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            def transform(self, profile: Profile) -> str:\n\"\"\"Transform the Profile into a OSCO yaml.\"\"\"\n    self._profile = profile\n    self._osco_version = self._get_normalized_version('osco_version', '0.1.46')\n    # set values\n    set_values = self._get_set_values()\n    # spec\n    if self._osco_version < (0, 1, 40):\n        # for versions prior to 0.1.40, exclude 'description'\n        spec = {\n            'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n            'title': self._profile.metadata.title,\n            'setValues': set_values,\n        }\n    else:\n        # for versions 0.1.40 and beyond, include 'description'\n        spec = {\n            'description': self._get_metadata_prop_value('profile_mnemonic', self._name),\n            'extends': self._get_metadata_prop_value('base_profile_mnemonic', self._extends),\n            'title': self._profile.metadata.title,\n            'setValues': set_values,\n        }\n    disable_rules = self._get_disable_rules()\n    if disable_rules:\n        spec['disableRules'] = disable_rules\n    # yaml data\n    ydata = {\n        'apiVersion': self._api_version,\n        'kind': self._kind,\n        'metadata': {\n            'name': self._get_metadata_prop_value('profile_mnemonic', self._name),\n            'namespace': self._namespace,\n        },\n        'spec': spec,\n    }\n    return json.dumps(ydata)\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer","title":" OscoResultToOscalARTransformer (ResultsTransformer) ","text":"

                                                                            Interface for Osco transformer.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            class OscoResultToOscalARTransformer(ResultsTransformer):\n\"\"\"Interface for Osco transformer.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._modes = {}\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"Analysis.\"\"\"\n        return self._results_factory.analysis\n\n    @property\n    def checking(self):\n\"\"\"Return checking.\"\"\"\n        return self._modes.get('checking', False)\n\n    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n        if modes is not None:\n            self._modes = modes\n\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n        The expected blob is a string that is one of:\n            - data from OpenShift Compliance Operator (json, yaml, xml)\n            - data from Auditree OSCO fetcher/check (json)\n        \"\"\"\n        results = None\n        self._results_factory = _OscalResultsFactory(self.get_timestamp(), self.checking)\n        if results is None:\n            results = self._ingest_xml(blob)\n        if results is None:\n            results = self._ingest_json(blob)\n        if results is None:\n            results = self._ingest_yaml(blob)\n        return results\n\n    def _ingest_xml(self, blob: str) -> Results:\n\"\"\"Ingest xml data.\"\"\"\n        # ?xml data\n        if blob.startswith('<?xml'):\n            resource = blob\n            self._results_factory.ingest_xml(resource)\n        else:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_json(self, blob: str) -> Results:\n\"\"\"Ingest json data.\"\"\"\n        try:\n            # ? configmaps or auditree data\n            jdata = json.loads(blob)\n            # https://docs.openshift.com/container-platform/3.7/rest_api/api/v1.ConfigMap.html#Get-api-v1-namespaces-namespace-configmaps-name\n            if 'kind' in jdata.keys() and jdata['kind'] == 'ConfigMapList' and 'items' in jdata.keys():\n                items = jdata['items']\n                for item in items:\n                    if 'data' in item.keys():\n                        data = item['data']\n                        if 'results' in data:\n                            resource = item\n                            self._results_factory.ingest(resource)\n            # https://github.com/ComplianceAsCode/auditree-arboretum/blob/main/arboretum/kubernetes/fetchers/fetch_cluster_resource.py\n            else:\n                for key in jdata.keys():\n                    for group in jdata[key]:\n                        for cluster in jdata[key][group]:\n                            if 'resources' in cluster:\n                                for resource in cluster['resources']:\n                                    self._results_factory.ingest(resource)\n        except json.decoder.JSONDecodeError:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_yaml(self, blob: str) -> Results:\n\"\"\"Ingest yaml data.\"\"\"\n        try:\n            # ? yaml data\n            yaml = YAML(typ='safe')\n            resource = yaml.load(blob)\n            self._results_factory.ingest(resource)\n        except Exception as e:\n            raise e\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.analysis","title":"analysis: List[str] property readonly","text":"

                                                                            Analysis.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.checking","title":"checking property readonly","text":"

                                                                            Return checking.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.__init__","title":"__init__(self) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._modes = {}\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.set_modes","title":"set_modes(self, modes)","text":"

                                                                            Keep modes info.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n    if modes is not None:\n        self._modes = modes\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoResultToOscalARTransformer.transform","title":"transform(self, blob)","text":"

                                                                            Transform the blob into a Results.

                                                                            The expected blob is a string that is one of: - data from OpenShift Compliance Operator (json, yaml, xml) - data from Auditree OSCO fetcher/check (json)

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n    The expected blob is a string that is one of:\n        - data from OpenShift Compliance Operator (json, yaml, xml)\n        - data from Auditree OSCO fetcher/check (json)\n    \"\"\"\n    results = None\n    self._results_factory = _OscalResultsFactory(self.get_timestamp(), self.checking)\n    if results is None:\n        results = self._ingest_xml(blob)\n    if results is None:\n        results = self._ingest_json(blob)\n    if results is None:\n        results = self._ingest_yaml(blob)\n    return results\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.OscoTransformer","title":" OscoTransformer (OscoResultToOscalARTransformer) ","text":"

                                                                            Legacy class name.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            class OscoTransformer(OscoResultToOscalARTransformer):\n\"\"\"Legacy class name.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse","title":" RuleUse ","text":"

                                                                            Represents one rule of OSCO data.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            class RuleUse():\n\"\"\"Represents one rule of OSCO data.\"\"\"\n\n    def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self.id_ = args['id_']\n        self.target = args['target']\n        self.target_type = args['target_type']\n        self.host_name = args['host_name']\n        self.benchmark_href = args['benchmark_href']\n        self.benchmark_id = args['benchmark_id']\n        self.scanner_name = args['scanner_name']\n        self.scanner_version = args['scanner_version']\n        self.idref = args['idref']\n        self.version = args['version']\n        self.time = args['time']\n        self.result = args['result']\n        self.severity = args['severity']\n        self.weight = args['weight']\n\n    @property\n    def inventory_key(self):\n\"\"\"Derive inventory key.\"\"\"\n        if self.host_name is None:\n            # OpenScap 1.3.3\n            rval = self.target + ':' + self.target_type\n        else:\n            # OpenScap 1.3.5\n            rval = self.host_name + ':' + self.target_type\n        return rval\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse.inventory_key","title":"inventory_key property readonly","text":"

                                                                            Derive inventory key.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.osco/#trestle.transforms.implementations.osco.RuleUse.__init__","title":"__init__(self, args) special","text":"

                                                                            Initialize given specified args.

                                                                            Source code in trestle/transforms/implementations/osco.py
                                                                            def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self.id_ = args['id_']\n    self.target = args['target']\n    self.target_type = args['target_type']\n    self.host_name = args['host_name']\n    self.benchmark_href = args['benchmark_href']\n    self.benchmark_id = args['benchmark_id']\n    self.scanner_name = args['scanner_name']\n    self.scanner_version = args['scanner_version']\n    self.idref = args['idref']\n    self.version = args['version']\n    self.time = args['time']\n    self.result = args['result']\n    self.severity = args['severity']\n    self.weight = args['weight']\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/","title":"tanium","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium","title":"trestle.transforms.implementations.tanium","text":"

                                                                            Facilitate Tanium result to NIST OSCAL transformation.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.logger","title":"logger","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUse","title":" RuleUse ","text":"

                                                                            Represents one row of Tanium data.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            class RuleUse():\n\"\"\"Represents one row of Tanium data.\"\"\"\n\n    def __init__(self, tanium_row: Dict[str, Any], comply: Dict[str, str], default_timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        logger.debug(f'tanium-row: {tanium_row}')\n        try:\n            # level 1 keys\n            self.computer_name = tanium_row['Computer Name']\n            self.tanium_client_ip_address = tanium_row['Tanium Client IP Address']\n            self.ip_address = str(tanium_row['IP Address'])\n            self.count = str(tanium_row['Count'])\n            # comply keys\n            self.check_id = comply['Check ID']\n            self.rule_id = comply['Rule ID']\n            self.state = comply['State']\n            # defaults\n            no_results = '[no results]'\n            self.check_id_level = no_results\n            self.check_id_version = no_results\n            self.check_id_benchmark = no_results\n            self.component = no_results\n            self.component_type = no_results\n            # parse\n            if ';' in self.check_id:\n                items = self.check_id.split(';')\n                if len(items) > 2:\n                    self.check_id_level = items[2]\n                if len(items) > 1:\n                    self.check_id_version = items[1]\n                if len(items) > 0:\n                    self.check_id_benchmark = items[0]\n                    self.component = items[0]\n                    if self.component.startswith('CIS '):\n                        self.component = self.component[len('CIS '):]\n                    if self.component.endswith(' Benchmark'):\n                        self.component = self.component[:-len(' Benchmark')]\n                    self.component_type = 'Operating System'\n            # timestamp\n            self.timestamp = comply.get('Timestamp', default_timestamp)\n            # collected\n            self.collected = default_timestamp\n        except Exception as e:\n            logger.debug(f'tanium-row: {tanium_row}')\n            logger.debug(e)\n            logger.debug(traceback.format_exc())\n            raise e\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUse-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUse.__init__","title":"__init__(self, tanium_row, comply, default_timestamp) special","text":"

                                                                            Initialize given specified args.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            def __init__(self, tanium_row: Dict[str, Any], comply: Dict[str, str], default_timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    logger.debug(f'tanium-row: {tanium_row}')\n    try:\n        # level 1 keys\n        self.computer_name = tanium_row['Computer Name']\n        self.tanium_client_ip_address = tanium_row['Tanium Client IP Address']\n        self.ip_address = str(tanium_row['IP Address'])\n        self.count = str(tanium_row['Count'])\n        # comply keys\n        self.check_id = comply['Check ID']\n        self.rule_id = comply['Rule ID']\n        self.state = comply['State']\n        # defaults\n        no_results = '[no results]'\n        self.check_id_level = no_results\n        self.check_id_version = no_results\n        self.check_id_benchmark = no_results\n        self.component = no_results\n        self.component_type = no_results\n        # parse\n        if ';' in self.check_id:\n            items = self.check_id.split(';')\n            if len(items) > 2:\n                self.check_id_level = items[2]\n            if len(items) > 1:\n                self.check_id_version = items[1]\n            if len(items) > 0:\n                self.check_id_benchmark = items[0]\n                self.component = items[0]\n                if self.component.startswith('CIS '):\n                    self.component = self.component[len('CIS '):]\n                if self.component.endswith(' Benchmark'):\n                    self.component = self.component[:-len(' Benchmark')]\n                self.component_type = 'Operating System'\n        # timestamp\n        self.timestamp = comply.get('Timestamp', default_timestamp)\n        # collected\n        self.collected = default_timestamp\n    except Exception as e:\n        logger.debug(f'tanium-row: {tanium_row}')\n        logger.debug(e)\n        logger.debug(traceback.format_exc())\n        raise e\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory","title":" RuleUseFactory ","text":"

                                                                            Build RuleUse list.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            class RuleUseFactory():\n\"\"\"Build RuleUse list.\"\"\"\n\n    def __init__(self, timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self._timestamp = timestamp\n\n    def _make_sublist(self, tanium_row: Dict[str, Any]) -> List[RuleUse]:\n\"\"\"Build RuleUse sublist from input data item.\"\"\"\n        retval = []\n        keys = tanium_row\n        for key in keys:\n            if key.startswith('Comply'):\n                break\n        comply_list = tanium_row[key]\n        for comply in comply_list:\n            rule_use = RuleUse(tanium_row, comply, self._timestamp)\n            retval.append(rule_use)\n        return retval\n\n    def make_list(self, blob: str) -> List[RuleUse]:\n\"\"\"Build RuleUse list from input data.\"\"\"\n        retval = []\n        lines = blob.splitlines()\n        for line in lines:\n            line = line.strip()\n            if line:\n                jdata = json.loads(line)\n                if type(jdata) is list:\n                    for item in jdata:\n                        logger.debug(f'item: {item}')\n                        retval += self._make_sublist(item)\n                else:\n                    logger.debug(f'jdata: {jdata}')\n                    retval += self._make_sublist(jdata)\n        logger.debug(f'ru_list: {len(retval)}')\n        return retval\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory.__init__","title":"__init__(self, timestamp) special","text":"

                                                                            Initialize given specified args.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            def __init__(self, timestamp: str) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self._timestamp = timestamp\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.RuleUseFactory.make_list","title":"make_list(self, blob)","text":"

                                                                            Build RuleUse list from input data.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            def make_list(self, blob: str) -> List[RuleUse]:\n\"\"\"Build RuleUse list from input data.\"\"\"\n    retval = []\n    lines = blob.splitlines()\n    for line in lines:\n        line = line.strip()\n        if line:\n            jdata = json.loads(line)\n            if type(jdata) is list:\n                for item in jdata:\n                    logger.debug(f'item: {item}')\n                    retval += self._make_sublist(item)\n            else:\n                logger.debug(f'jdata: {jdata}')\n                retval += self._make_sublist(jdata)\n    logger.debug(f'ru_list: {len(retval)}')\n    return retval\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory","title":" TaniumOscalFactory ","text":"

                                                                            Build Tanium OSCAL entities.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            class TaniumOscalFactory():\n\"\"\"Build Tanium OSCAL entities.\"\"\"\n\n    def __init__(\n        self,\n        timestamp: str,\n        rule_use_list: List[RuleUse],\n        blocksize: int = 11000,\n        cpus_max: int = 1,\n        cpus_min: int = 1,\n        checking: bool = False,\n        caching: bool = True,\n        aggregate: bool = True\n    ) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self._rule_use_list = rule_use_list\n        self._timestamp = timestamp\n        self._component_map: Dict[str, SystemComponent] = {}\n        self._inventory_map: Dict[str, InventoryItem] = {}\n        self._observation_list: List[Observation] = []\n        self._ns = 'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium'\n        self._cpus = None\n        self._checking = checking\n        self._caching = caching\n        self._aggregate = aggregate\n        self._result = None\n        # blocksize: default, min\n        self._blocksize = blocksize\n        if self._blocksize < 1:\n            self._blocksize = 1\n        # cpus max: default, max, min\n        self._cpus_max = cpus_max\n        if self._cpus_max > os.cpu_count():\n            self._cpus_max = os.cpu_count()\n        self._cpus_min = cpus_min\n        if self._cpus_min > self._cpus_max:\n            self._cpus_min = self._cpus_max\n        if self._cpus_min < 1:\n            self._cpus_min = 1\n        self._property_accounting = PropertyAccounting()\n        self._property_manager = PropertyManager(caching=caching, checking=checking)\n\n    def _is_duplicate_component(self, rule_use: RuleUse) -> bool:\n\"\"\"Check for duplicate component.\"\"\"\n        retval = False\n        component_type = rule_use.component_type\n        component_title = rule_use.component\n        for component in self._component_map.values():\n            if component.type != component_type:\n                continue\n            if component.title != component_title:\n                continue\n            retval = True\n            break\n        return retval\n\n    def _derive_components(self) -> None:\n\"\"\"Derive components from RuleUse list.\"\"\"\n        self._component_map: Dict[str, SystemComponent] = {}\n        for rule_use in self._rule_use_list:\n            if self._is_duplicate_component(rule_use):\n                continue\n            component_type = rule_use.component_type\n            component_title = rule_use.component\n            # See Note in _get_component_ref.\n            component_description = rule_use.component\n            component_ref = _uuid_component()\n            status = Status(state='operational')\n            component = SystemComponent(\n                uuid=component_ref,\n                type=component_type,\n                title=component_title,\n                description=component_description,\n                status=status\n            )\n            self._component_map[component_ref] = component\n\n    def _get_component_ref(self, rule_use: RuleUse) -> Optional[str]:\n\"\"\"Get component reference for specified rule use.\"\"\"\n        uuid = None\n        for component_ref, component in self._component_map.items():\n            if component.type != rule_use.component_type:\n                continue\n            if component.title != rule_use.component:\n                continue\n            # Note: currently title and description are the same,\n            # therefore checking description is not necessary.\n            uuid = component_ref\n            break\n        return uuid\n\n    def _derive_inventory(self) -> None:\n\"\"\"Derive inventory from RuleUse list.\"\"\"\n        self._inventory_map: Dict[str, InventoryItem] = {}\n        for rule_use in self._rule_use_list:\n            if rule_use.tanium_client_ip_address in self._inventory_map:\n                continue\n            inventory = InventoryItem(uuid=_uuid_inventory(), description='inventory')\n            inventory.props = [\n                self._property_manager.materialize(name='Computer_Name', value=rule_use.computer_name, ns=self._ns),\n                self._property_manager.materialize(\n                    name='Tanium_Client_IP_Address',\n                    value=rule_use.tanium_client_ip_address,\n                    ns=self._ns,\n                    class_='scc_inventory_item_id'\n                ),\n                self._property_manager.materialize(name='IP_Address', value=rule_use.ip_address, ns=self._ns),\n                self._property_manager.materialize(name='Count', value=rule_use.count, ns=self._ns)\n            ]\n            component_uuid = self._get_component_ref(rule_use)\n            if component_uuid is not None:\n                inventory.implemented_components = [ImplementedComponent(component_uuid=component_uuid)]\n            self._inventory_map[rule_use.tanium_client_ip_address] = inventory\n\n    def _get_inventory_ref(self, rule_use: RuleUse) -> str:\n\"\"\"Get inventory reference for specified rule use.\"\"\"\n        return self._inventory_map[rule_use.tanium_client_ip_address].uuid\n\n    def _conditional_include(\n        self,\n        props: List[Property],\n        group: str = None,\n        name: str = None,\n        value: str = None,\n        ns: str = None,\n        class_: str = None\n    ) -> None:\n\"\"\"Add non-aggregated property or remember common property.\"\"\"\n        if self._aggregate:\n            if self._property_accounting.is_common_property(group=group, name=name, value=value, ns=ns, class_=class_):\n                # common property\n                self._property_manager.put_common_property(group=group, name=name, value=value, ns=ns, class_=class_)\n                return\n        # non-aggregated property\n        props.append(self._property_manager.materialize(name=name, value=value, ns=ns, class_=class_))\n\n    def _get_observtion_properties(self, rule_use: RuleUse) -> List[Property]:\n\"\"\"Get observation properties.\"\"\"\n        props = []\n        group = self._get_component_ref(rule_use)\n        self._conditional_include(props=props, group=group, name='Check_ID', value=rule_use.check_id, ns=self._ns)\n        self._conditional_include(\n            props=props,\n            group=group,\n            name='Check_ID_Benchmark',\n            value=rule_use.check_id_benchmark,\n            ns=self._ns,\n            class_='scc_predefined_profile'\n        )\n        self._conditional_include(\n            props=props,\n            group=group,\n            name='Check_ID_Version',\n            value=rule_use.check_id_version,\n            ns=self._ns,\n            class_='scc_predefined_profile_version'\n        )\n        self._conditional_include(\n            props=props, group=group, name='Check_ID_Level', value=rule_use.check_id_level, ns=self._ns\n        )\n        self._conditional_include(\n            props=props,\n            group=group,\n            name='Rule_ID',\n            value=rule_use.rule_id,\n            ns=self._ns,\n            class_='scc_goal_description'\n        )\n        self._conditional_include(\n            props=props, group=group, name='Rule_ID', value=rule_use.rule_id, ns=self._ns, class_='scc_check_name_id'\n        )\n        self._conditional_include(\n            props=props, group=group, name='State', value=rule_use.state, ns=self._ns, class_='scc_result'\n        )\n        self._conditional_include(\n            props=props, group=group, name='Timestamp', value=rule_use.timestamp, ns=self._ns, class_='scc_timestamp'\n        )\n        return props\n\n    def _derive_common_property_accounting(self) -> None:\n\"\"\"Derive common properties accounting from RuleUse list.\"\"\"\n        for rule_use in self._rule_use_list:\n            group = self._get_component_ref(rule_use)\n            self._property_accounting.count_group(group=group)\n            self._property_accounting.count_property(group=group, name='Check_ID', value=rule_use.check_id, ns=self._ns)\n            self._property_accounting.count_property(\n                group=group,\n                name='Check_ID_Benchmark',\n                value=rule_use.check_id_benchmark,\n                ns=self._ns,\n                class_='scc_predefined_profile'\n            )\n            self._property_accounting.count_property(\n                group=group,\n                name='Check_ID_Version',\n                value=rule_use.check_id_version,\n                ns=self._ns,\n                class_='scc_predefined_profile_version'\n            )\n            self._property_accounting.count_property(\n                group=group, name='Check_ID_Level', value=rule_use.check_id_level, ns=self._ns\n            )\n            self._property_accounting.count_property(\n                group=group, name='Rule_ID', value=rule_use.rule_id, ns=self._ns, class_='scc_goal_description'\n            )\n            self._property_accounting.count_property(\n                group=group, name='Rule_ID', value=rule_use.rule_id, ns=self._ns, class_='scc_check_name_id'\n            )\n            self._property_accounting.count_property(\n                group=group, name='State', value=rule_use.state, ns=self._ns, class_='scc_result'\n            )\n            self._property_accounting.count_property(\n                group=group, name='Timestamp', value=rule_use.timestamp, ns=self._ns, class_='scc_timestamp'\n            )\n\n    # parallel process to process one chuck of entire data set\n    def _batch_observations(self, index: int) -> Dict[str, List[Observation]]:\n\"\"\"Derive batch of observations from RuleUse list.\"\"\"\n        observation_partial_map: Dict[str, List[Observation]] = {}\n        # determine which chunk to process\n        batch_size = (len(self._rule_use_list) // self._batch_workers) + 1\n        start = index * batch_size\n        end = (index + 1) * batch_size\n        end = min(end, len(self._rule_use_list))\n        logger.debug(f'start: {start} end: {end-1}')\n        # process just the one chunk\n        for i in range(start, end):\n            rule_use = self._rule_use_list[i]\n            observation = Observation(\n                uuid=_uuid_observation(),\n                description=rule_use.rule_id,\n                methods=['TEST-AUTOMATED'],\n                collected=rule_use.collected\n            )\n            subject_uuid = self._get_inventory_ref(rule_use)\n            subject_reference = SubjectReference(subject_uuid=subject_uuid, type='inventory-item')\n            observation.subjects = [subject_reference]\n            observation.props = self._get_observtion_properties(rule_use)\n            observation_partial_map[subject_uuid] = observation_partial_map.get(subject_uuid, []) + [observation]\n        return observation_partial_map\n\n    @property\n    def _batch_workers(self) -> int:\n\"\"\"Calculate number of parallel processes to employ.\"\"\"\n        if self._cpus is None:\n            cpus_estimate = len(self._rule_use_list) // self._blocksize\n            self._cpus = max(min(cpus_estimate, self._cpus_max), self._cpus_min)\n            logger.debug(f'CPUs estimate: {cpus_estimate} available: {os.cpu_count()} selection: {self._cpus}')\n        return self._cpus\n\n    def _derive_observations(self) -> None:\n\"\"\"Derive observations from RuleUse list.\"\"\"\n        self._observation_map = {}\n        if self._batch_workers == 1:\n            # no need for multiprocessing\n            self._observation_map = self._batch_observations(0)\n        else:\n            # use multiprocessing to perform observations creation in parallel\n            pool = multiprocessing.Pool(processes=self._batch_workers)\n            rval_list = pool.map(self._batch_observations, range(self._batch_workers))\n            # gather observations from the sundry batch workers\n            for partial_observation_map in rval_list:\n                self._observation_map = join_key_to_list_dicts(self._observation_map, partial_observation_map)\n\n    @property\n    def components(self) -> List[SystemComponent]:\n\"\"\"OSCAL components.\"\"\"\n        return list(self._component_map.values())\n\n    @property\n    def inventory(self) -> ValuesView[InventoryItem]:\n\"\"\"OSCAL inventory.\"\"\"\n        return self._inventory_map.values()\n\n    @property\n    def observations(self) -> List[Observation]:\n\"\"\"OSCAL observations.\"\"\"\n        rval = []\n        # observations are partitioned by local-definition uuid; join them into one list\n        for key in self._observation_map:\n            list_ = self._observation_map[key]\n            for observation in list_:\n                rval.append(observation)\n        return rval\n\n    @property\n    def control_selections(self) -> List[ControlSelection]:\n\"\"\"OSCAL control selections.\"\"\"\n        rval = []\n        rval.append(ControlSelection())\n        return rval\n\n    @property\n    def reviewed_controls(self) -> ReviewedControls:\n\"\"\"OSCAL reviewed controls.\"\"\"\n        rval = ReviewedControls(control_selections=self.control_selections)\n        return rval\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"OSCAL statistics.\"\"\"\n        analysis = []\n        analysis.append(f'components: {len(self.components)}')\n        analysis.append(f'inventory: {len(self.inventory)}')\n        analysis.append(f'observations: {len(self.observations)}')\n        analysis.append(f'cache: requests={self._property_manager.requests} hits={self._property_manager.hits}')\n        return analysis\n\n    def _get_local_definitions(self, system_component: SystemComponent) -> LocalDefinitions1:\n\"\"\"Get local definitions.\"\"\"\n        rval = LocalDefinitions1()\n        for component in self.components:\n            if component.uuid == system_component.uuid:\n                rval.components = [component]\n                rval.inventory_items = []\n                for inventory_item in self.inventory:\n                    for implemented_component in inventory_item.implemented_components:\n                        if implemented_component.component_uuid == system_component.uuid:\n                            rval.inventory_items.append(inventory_item)\n                break\n        return rval\n\n    def _get_local_definitions_uuids(self, local_definitions: LocalDefinitions1) -> List[str]:\n\"\"\"Get inventory uuids for given local definitions.\"\"\"\n        rval = []\n        if local_definitions.inventory_items:\n            rval = [inventory_item.uuid for inventory_item in local_definitions.inventory_items]\n        return rval\n\n    def _get_observations_for_uuid(self, uuid_: str) -> List[Observation]:\n\"\"\"Get observations for given uuid.\"\"\"\n        rval = 0\n        if uuid_ in self._observation_map:\n            rval = []\n            list_ = self._observation_map[uuid_]\n            for observation in list_:\n                rval.append(observation)\n        return rval\n\n    def _get_observations(self, local_definitions: LocalDefinitions1) -> List[Observation]:\n\"\"\"Get observations for given local definitions.\"\"\"\n        rval = []\n        local_definitions_uuids = self._get_local_definitions_uuids(local_definitions)\n        for uuid_ in local_definitions_uuids:\n            observations = self._get_observations_for_uuid(uuid_)\n            if observations:\n                rval += observations\n        return rval\n\n    def _get_properties(self, group: str) -> List[Property]:\n\"\"\"Get properties for given group.\"\"\"\n        return self._property_manager.get_common_properties(group)\n\n    @property\n    def results(self) -> List[Result]:\n\"\"\"OSCAL result.\"\"\"\n        if self._result is None:\n            self._derive_components()\n            self._derive_inventory()\n            if self._aggregate:\n                self._derive_common_property_accounting()\n            self._derive_observations()\n        results = []\n        for component in self.components:\n            local_definitions = self._get_local_definitions(component)\n            observations = self._get_observations(local_definitions)\n            result = Result(\n                uuid=_uuid_result(),\n                title='Tanium',\n                description='Tanium',\n                start=self._timestamp,\n                end=self._timestamp,\n                reviewed_controls=self.reviewed_controls,\n                local_definitions=local_definitions,\n                observations=observations\n            )\n            component_ref = component.uuid\n            result.props = self._get_properties(component_ref)\n            results.append(result)\n        return results\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.analysis","title":"analysis: List[str] property readonly","text":"

                                                                            OSCAL statistics.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.components","title":"components: List[trestle.oscal.common.SystemComponent] property readonly","text":"

                                                                            OSCAL components.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.control_selections","title":"control_selections: List[trestle.oscal.common.ControlSelection] property readonly","text":"

                                                                            OSCAL control selections.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.inventory","title":"inventory: ValuesView[trestle.oscal.common.InventoryItem] property readonly","text":"

                                                                            OSCAL inventory.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.observations","title":"observations: List[trestle.oscal.common.Observation] property readonly","text":"

                                                                            OSCAL observations.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.results","title":"results: List[trestle.oscal.assessment_results.Result] property readonly","text":"

                                                                            OSCAL result.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.reviewed_controls","title":"reviewed_controls: ReviewedControls property readonly","text":"

                                                                            OSCAL reviewed controls.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumOscalFactory.__init__","title":"__init__(self, timestamp, rule_use_list, blocksize=11000, cpus_max=1, cpus_min=1, checking=False, caching=True, aggregate=True) special","text":"

                                                                            Initialize given specified args.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            def __init__(\n    self,\n    timestamp: str,\n    rule_use_list: List[RuleUse],\n    blocksize: int = 11000,\n    cpus_max: int = 1,\n    cpus_min: int = 1,\n    checking: bool = False,\n    caching: bool = True,\n    aggregate: bool = True\n) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self._rule_use_list = rule_use_list\n    self._timestamp = timestamp\n    self._component_map: Dict[str, SystemComponent] = {}\n    self._inventory_map: Dict[str, InventoryItem] = {}\n    self._observation_list: List[Observation] = []\n    self._ns = 'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium'\n    self._cpus = None\n    self._checking = checking\n    self._caching = caching\n    self._aggregate = aggregate\n    self._result = None\n    # blocksize: default, min\n    self._blocksize = blocksize\n    if self._blocksize < 1:\n        self._blocksize = 1\n    # cpus max: default, max, min\n    self._cpus_max = cpus_max\n    if self._cpus_max > os.cpu_count():\n        self._cpus_max = os.cpu_count()\n    self._cpus_min = cpus_min\n    if self._cpus_min > self._cpus_max:\n        self._cpus_min = self._cpus_max\n    if self._cpus_min < 1:\n        self._cpus_min = 1\n    self._property_accounting = PropertyAccounting()\n    self._property_manager = PropertyManager(caching=caching, checking=checking)\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer","title":" TaniumResultToOscalARTransformer (ResultsTransformer) ","text":"

                                                                            Interface for Tanium transformer.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            class TaniumResultToOscalARTransformer(ResultsTransformer):\n\"\"\"Interface for Tanium transformer.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._modes = {}\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"Return analysis info.\"\"\"\n        return self._analysis\n\n    @property\n    def blocksize(self) -> int:\n\"\"\"Return blocksize.\"\"\"\n        return self._modes.get('blocksize', 10000)\n\n    @property\n    def cpus_max(self) -> int:\n\"\"\"Return cpus_max.\"\"\"\n        return self._modes.get('cpus_max', 1)\n\n    @property\n    def cpus_min(self) -> int:\n\"\"\"Return cpus_min.\"\"\"\n        return self._modes.get('cpus_min', 1)\n\n    @property\n    def aggregate(self) -> bool:\n\"\"\"Return aggregate.\"\"\"\n        return self._modes.get('aggregate', True)\n\n    @property\n    def caching(self) -> bool:\n\"\"\"Return caching.\"\"\"\n        return self._modes.get('caching', True)\n\n    @property\n    def checking(self) -> bool:\n\"\"\"Return checking.\"\"\"\n        return self._modes.get('checking', False)\n\n    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n        if modes is not None:\n            self._modes = modes\n\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\"\"\"\n        ts0 = datetime.datetime.now()\n        results = Results()\n        ru_factory = RuleUseFactory(self.get_timestamp())\n        ru_list = ru_factory.make_list(blob)\n        tanium_oscal_factory = TaniumOscalFactory(\n            self.get_timestamp(),\n            ru_list,\n            self.blocksize,\n            self.cpus_max,\n            self.cpus_min,\n            self.checking,\n            self.caching,\n            self.aggregate\n        )\n        results.__root__ = tanium_oscal_factory.results\n        ts1 = datetime.datetime.now()\n        self._analysis = tanium_oscal_factory.analysis\n        self._analysis.append(f'transform time: {ts1-ts0}')\n        return results\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.aggregate","title":"aggregate: bool property readonly","text":"

                                                                            Return aggregate.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.analysis","title":"analysis: List[str] property readonly","text":"

                                                                            Return analysis info.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.blocksize","title":"blocksize: int property readonly","text":"

                                                                            Return blocksize.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.caching","title":"caching: bool property readonly","text":"

                                                                            Return caching.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.checking","title":"checking: bool property readonly","text":"

                                                                            Return checking.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.cpus_max","title":"cpus_max: int property readonly","text":"

                                                                            Return cpus_max.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.cpus_min","title":"cpus_min: int property readonly","text":"

                                                                            Return cpus_min.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.__init__","title":"__init__(self) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._modes = {}\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.set_modes","title":"set_modes(self, modes)","text":"

                                                                            Keep modes info.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n    if modes is not None:\n        self._modes = modes\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumResultToOscalARTransformer.transform","title":"transform(self, blob)","text":"

                                                                            Transform the blob into a Results.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\"\"\"\n    ts0 = datetime.datetime.now()\n    results = Results()\n    ru_factory = RuleUseFactory(self.get_timestamp())\n    ru_list = ru_factory.make_list(blob)\n    tanium_oscal_factory = TaniumOscalFactory(\n        self.get_timestamp(),\n        ru_list,\n        self.blocksize,\n        self.cpus_max,\n        self.cpus_min,\n        self.checking,\n        self.caching,\n        self.aggregate\n    )\n    results.__root__ = tanium_oscal_factory.results\n    ts1 = datetime.datetime.now()\n    self._analysis = tanium_oscal_factory.analysis\n    self._analysis.append(f'transform time: {ts1-ts0}')\n    return results\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.tanium/#trestle.transforms.implementations.tanium.TaniumTransformer","title":" TaniumTransformer (TaniumResultToOscalARTransformer) ","text":"

                                                                            Legacy class name.

                                                                            Source code in trestle/transforms/implementations/tanium.py
                                                                            class TaniumTransformer(TaniumResultToOscalARTransformer):\n\"\"\"Legacy class name.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/","title":"xccdf","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf","title":"trestle.transforms.implementations.xccdf","text":"

                                                                            Facilitate OSCAL-XCCDF transformation.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse","title":" RuleUse ","text":"

                                                                            Represents one rule of XCCDF data.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            class RuleUse():\n\"\"\"Represents one rule of XCCDF data.\"\"\"\n\n    def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n        self.id_ = args['id_']\n        self.target = args['target']\n        self.target_type = args['target_type']\n        self.host_name = args['host_name']\n        self.benchmark_href = args['benchmark_href']\n        self.benchmark_id = args['benchmark_id']\n        self.scanner_name = args['scanner_name']\n        self.scanner_version = args['scanner_version']\n        self.idref = args['idref']\n        self.version = args['version']\n        self.time = args['time']\n        self.result = args['result']\n        self.severity = args['severity']\n        self.weight = args['weight']\n\n    @property\n    def inventory_key(self):\n\"\"\"Derive inventory key.\"\"\"\n        if self.host_name is None:\n            # OpenScap 1.3.3\n            rval = self.target + ':' + self.target_type\n        else:\n            # OpenScap 1.3.5\n            rval = self.host_name + ':' + self.target_type\n        return rval\n\n    @property\n    def ns(self):\n\"\"\"Derive namespace.\"\"\"\n        return f'https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/{self.scanner_name}'  # noqa: E231\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse.inventory_key","title":"inventory_key property readonly","text":"

                                                                            Derive inventory key.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse.ns","title":"ns property readonly","text":"

                                                                            Derive namespace.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.RuleUse.__init__","title":"__init__(self, args) special","text":"

                                                                            Initialize given specified args.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def __init__(self, args: Dict[str, str]) -> None:\n\"\"\"Initialize given specified args.\"\"\"\n    self.id_ = args['id_']\n    self.target = args['target']\n    self.target_type = args['target_type']\n    self.host_name = args['host_name']\n    self.benchmark_href = args['benchmark_href']\n    self.benchmark_id = args['benchmark_id']\n    self.scanner_name = args['scanner_name']\n    self.scanner_version = args['scanner_version']\n    self.idref = args['idref']\n    self.version = args['version']\n    self.time = args['time']\n    self.result = args['result']\n    self.severity = args['severity']\n    self.weight = args['weight']\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer","title":" XccdfResultToOscalARTransformer (ResultsTransformer) ","text":"

                                                                            Interface for Xccdf transformer.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            class XccdfResultToOscalARTransformer(ResultsTransformer):\n\"\"\"Interface for Xccdf transformer.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._modes = {}\n\n    @property\n    def analysis(self) -> List[str]:\n\"\"\"Analysis.\"\"\"\n        return self._results_factory.analysis\n\n    @property\n    def checking(self):\n\"\"\"Return checking.\"\"\"\n        return self._modes.get('checking', False)\n\n    @property\n    def tags(self):\n\"\"\"Return tags.\"\"\"\n        return self._tags\n\n    def set_tags(self, tags: Dict[str, str]) -> None:\n\"\"\"Keep tags info (property name to property class).\"\"\"\n        self._tags = tags\n\n    def set_title(self, title: str) -> None:\n\"\"\"Keep title info.\"\"\"\n        self._title = title\n\n    def set_description(self, description: str) -> None:\n\"\"\"Keep description info.\"\"\"\n        self._description = description\n\n    def set_type(self, type_: str) -> None:\n\"\"\"Keep type info.\"\"\"\n        self._type = type_\n\n    def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n        if modes is not None:\n            self._modes = modes\n\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n        The expected blob is a string that is one of:\n            - data from OpenShift Compliance Operator (json, yaml, xml)\n            - data from Auditree XCCDF fetcher/check (json)\n        \"\"\"\n        self._results_factory = _OscalResultsFactory(\n            self._title, self._description, self._type, self.get_timestamp(), self.checking, self.tags\n        )\n        results = self._ingest_xml(blob)\n        if results is None:\n            results = self._ingest_json(blob)\n        if results is None:\n            results = self._ingest_yaml(blob)\n        return results\n\n    def _ingest_xml(self, blob: str) -> Optional[Results]:\n\"\"\"Ingest xml data.\"\"\"\n        # ?xml data\n        if blob.startswith('<?xml'):\n            resource = blob\n            self._results_factory.ingest_xml(resource)\n        else:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_configmaps(self, jdata: dict) -> None:\n\"\"\"Ingest configmaps.\"\"\"\n        items = jdata['items']\n        for item in items:\n            if 'data' in item.keys():\n                data = item['data']\n                if 'results' in data:\n                    resource = item\n                    self._results_factory.ingest(resource)\n\n    def _ingest_auditree(self, jdata: dict) -> None:\n\"\"\"Ingest auditree.\"\"\"\n        for key in jdata.keys():\n            for group in jdata[key]:\n                for cluster in jdata[key][group]:\n                    if 'resources' in cluster:\n                        for resource in cluster['resources']:\n                            self._results_factory.ingest(resource)\n\n    def _ingest_json(self, blob: str) -> Optional[Results]:\n\"\"\"Ingest json data.\"\"\"\n        try:\n            # ? configmaps or auditree data\n            jdata = json.loads(blob)\n            # https://docs.openshift.com/container-platform/3.7/rest_api/api/v1.ConfigMap.html#Get-api-v1-namespaces-namespace-configmaps-name\n            if 'kind' in jdata.keys() and jdata['kind'] == 'ConfigMapList' and 'items' in jdata.keys():\n                self._ingest_configmaps(jdata)\n            # https://github.com/ComplianceAsCode/auditree-arboretum/blob/main/arboretum/kubernetes/fetchers/fetch_cluster_resource.py\n            else:\n                self._ingest_auditree(jdata)\n        except json.decoder.JSONDecodeError:\n            return None\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n\n    def _ingest_yaml(self, blob: str) -> Results:\n\"\"\"Ingest yaml data.\"\"\"\n        try:\n            # ? yaml data\n            yaml = YAML(typ='safe')\n            resource = yaml.load(blob)\n            self._results_factory.ingest(resource)\n        except Exception as e:\n            raise RuntimeError(e)\n        results = Results()\n        results.__root__.append(self._results_factory.result)\n        return results\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.analysis","title":"analysis: List[str] property readonly","text":"

                                                                            Analysis.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.checking","title":"checking property readonly","text":"

                                                                            Return checking.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.tags","title":"tags property readonly","text":"

                                                                            Return tags.

                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.__init__","title":"__init__(self) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._modes = {}\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_description","title":"set_description(self, description)","text":"

                                                                            Keep description info.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def set_description(self, description: str) -> None:\n\"\"\"Keep description info.\"\"\"\n    self._description = description\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_modes","title":"set_modes(self, modes)","text":"

                                                                            Keep modes info.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def set_modes(self, modes: Dict[str, Any]) -> None:\n\"\"\"Keep modes info.\"\"\"\n    if modes is not None:\n        self._modes = modes\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_tags","title":"set_tags(self, tags)","text":"

                                                                            Keep tags info (property name to property class).

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def set_tags(self, tags: Dict[str, str]) -> None:\n\"\"\"Keep tags info (property name to property class).\"\"\"\n    self._tags = tags\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_title","title":"set_title(self, title)","text":"

                                                                            Keep title info.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def set_title(self, title: str) -> None:\n\"\"\"Keep title info.\"\"\"\n    self._title = title\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.set_type","title":"set_type(self, type_)","text":"

                                                                            Keep type info.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def set_type(self, type_: str) -> None:\n\"\"\"Keep type info.\"\"\"\n    self._type = type_\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfResultToOscalARTransformer.transform","title":"transform(self, blob)","text":"

                                                                            Transform the blob into a Results.

                                                                            The expected blob is a string that is one of: - data from OpenShift Compliance Operator (json, yaml, xml) - data from Auditree XCCDF fetcher/check (json)

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into a Results.\n\n    The expected blob is a string that is one of:\n        - data from OpenShift Compliance Operator (json, yaml, xml)\n        - data from Auditree XCCDF fetcher/check (json)\n    \"\"\"\n    self._results_factory = _OscalResultsFactory(\n        self._title, self._description, self._type, self.get_timestamp(), self.checking, self.tags\n    )\n    results = self._ingest_xml(blob)\n    if results is None:\n        results = self._ingest_json(blob)\n    if results is None:\n        results = self._ingest_yaml(blob)\n    return results\n
                                                                            "},{"location":"api_reference/trestle.transforms.implementations.xccdf/#trestle.transforms.implementations.xccdf.XccdfTransformer","title":" XccdfTransformer (XccdfResultToOscalARTransformer) ","text":"

                                                                            Legacy class name.

                                                                            Source code in trestle/transforms/implementations/xccdf.py
                                                                            class XccdfTransformer(XccdfResultToOscalARTransformer):\n\"\"\"Legacy class name.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.results/","title":"results","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results","title":"trestle.transforms.results","text":"

                                                                            Define Results class returned by transformers.

                                                                            "},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results","title":" Results (OscalBaseModel) pydantic-model","text":"

                                                                            Transformer results as a list.

                                                                            Source code in trestle/transforms/results.py
                                                                            class Results(OscalBaseModel):\n\"\"\"Transformer results as a list.\"\"\"\n\n    __root__: List[Result] = []\n
                                                                            "},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__class_vars__","title":"__class_vars__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__custom_root_type__","title":"__custom_root_type__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__doc__","title":"__doc__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__exclude_fields__","title":"__exclude_fields__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__fields__","title":"__fields__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__include_fields__","title":"__include_fields__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__post_root_validators__","title":"__post_root_validators__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__pre_root_validators__","title":"__pre_root_validators__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__private_attributes__","title":"__private_attributes__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__root__","title":"__root__: List[trestle.oscal.assessment_results.Result] pydantic-field special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__schema_cache__","title":"__schema_cache__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__signature__","title":"__signature__ special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__slots__","title":"__slots__: Tuple[str, ...] special","text":""},{"location":"api_reference/trestle.transforms.results/#trestle.transforms.results.Results.__validators__","title":"__validators__ special","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/","title":"transformer_factory","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory","title":"trestle.transforms.transformer_factory","text":"

                                                                            Define the TransformerFactory and corresponding transformer classes it creates.

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.FromOscalTransformer","title":" FromOscalTransformer (TransformerBase) ","text":"

                                                                            Abstract interface for transformers from OSCAL.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            class FromOscalTransformer(TransformerBase):\n\"\"\"Abstract interface for transformers from OSCAL.\"\"\"\n\n    @abstractmethod\n    def transform(self, obj: OscalBaseModel) -> str:\n\"\"\"Transform the from OSCAL.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.FromOscalTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.FromOscalTransformer.transform","title":"transform(self, obj)","text":"

                                                                            Transform the from OSCAL.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            @abstractmethod\ndef transform(self, obj: OscalBaseModel) -> str:\n\"\"\"Transform the from OSCAL.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ResultsTransformer","title":" ResultsTransformer (TransformerBase) ","text":"

                                                                            Abstract interface for transformers that specifically return Results.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            class ResultsTransformer(TransformerBase):\n\"\"\"Abstract interface for transformers that specifically return Results.\"\"\"\n\n    @abstractmethod\n    def transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into Results.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ResultsTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ResultsTransformer.transform","title":"transform(self, blob)","text":"

                                                                            Transform the blob into Results.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            @abstractmethod\ndef transform(self, blob: str) -> Results:\n\"\"\"Transform the blob into Results.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ToOscalTransformer","title":" ToOscalTransformer (TransformerBase) ","text":"

                                                                            Abstract interface for transformers to OSCAL.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            class ToOscalTransformer(TransformerBase):\n\"\"\"Abstract interface for transformers to OSCAL.\"\"\"\n\n    @abstractmethod\n    def transform(self, obj: str) -> OscalBaseModel:\n\"\"\"Transform the to OSCAL.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ToOscalTransformer-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.ToOscalTransformer.transform","title":"transform(self, obj)","text":"

                                                                            Transform the to OSCAL.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            @abstractmethod\ndef transform(self, obj: str) -> OscalBaseModel:\n\"\"\"Transform the to OSCAL.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase","title":" TransformerBase (ABC) ","text":"

                                                                            Abstract base interface for all transformers.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            class TransformerBase(ABC):\n\"\"\"Abstract base interface for all transformers.\"\"\"\n\n    # the current time for consistent timestamping\n    _timestamp = datetime.datetime.utcnow().replace(microsecond=0).replace(tzinfo=datetime.timezone.utc).isoformat()\n\n    @staticmethod\n    def set_timestamp(value: str) -> None:\n\"\"\"Set the default timestamp value.\"\"\"\n        datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')\n        TransformerBase._timestamp = value\n\n    @staticmethod\n    def get_timestamp() -> str:\n\"\"\"Get the default timestamp value.\"\"\"\n        return TransformerBase._timestamp\n\n    @abstractmethod\n    def transform(self, blob: Any) -> Any:\n\"\"\"Transform the blob into a general OscalBaseModel.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase.get_timestamp","title":"get_timestamp() staticmethod","text":"

                                                                            Get the default timestamp value.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            @staticmethod\ndef get_timestamp() -> str:\n\"\"\"Get the default timestamp value.\"\"\"\n    return TransformerBase._timestamp\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase.set_timestamp","title":"set_timestamp(value) staticmethod","text":"

                                                                            Set the default timestamp value.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            @staticmethod\ndef set_timestamp(value: str) -> None:\n\"\"\"Set the default timestamp value.\"\"\"\n    datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')\n    TransformerBase._timestamp = value\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerBase.transform","title":"transform(self, blob)","text":"

                                                                            Transform the blob into a general OscalBaseModel.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            @abstractmethod\ndef transform(self, blob: Any) -> Any:\n\"\"\"Transform the blob into a general OscalBaseModel.\"\"\"\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory","title":" TransformerFactory ","text":"

                                                                            Perform registration and creation of transformers.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            class TransformerFactory:\n\"\"\"Perform registration and creation of transformers.\"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize the transformers dictionary as empty.\"\"\"\n        self._transformers: Dict[str, Type[TransformerBase]] = {}\n\n    def register_transformer(self, name: str, transformer: Type[TransformerBase]) -> None:\n\"\"\"\n        Register the transformer.\n\n        This registers transformers in the factory so they may be created by name.\n\n        Args:\n            name (str): The name of the transformer.\n            transformer (TransformerBase): The transformer class to be registered.\n\n        Returns:\n            None\n        \"\"\"\n        self._transformers[name] = transformer\n\n    def get(self, name: str) -> TransformerBase:\n\"\"\"\n        Create an instance of the desired transformer based its name.\n\n        Args:\n            name (str): The name of the transformer.\n\n        Returns:\n            An instance of the desired transformer.\n\n        Raises:\n            TrestleError: if the name does not exist in the registry.\n        \"\"\"\n        t = self._transformers.get(name)\n        if t is not None:\n            return t()\n        raise TrestleError(f'Error getting non-registered transform {name}')\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory.__init__","title":"__init__(self) special","text":"

                                                                            Initialize the transformers dictionary as empty.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize the transformers dictionary as empty.\"\"\"\n    self._transformers: Dict[str, Type[TransformerBase]] = {}\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory.get","title":"get(self, name)","text":"

                                                                            Create an instance of the desired transformer based its name.

                                                                            Parameters:

                                                                            Name Type Description Default name str

                                                                            The name of the transformer.

                                                                            required

                                                                            Returns:

                                                                            Type Description TransformerBase

                                                                            An instance of the desired transformer.

                                                                            Exceptions:

                                                                            Type Description TrestleError

                                                                            if the name does not exist in the registry.

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            def get(self, name: str) -> TransformerBase:\n\"\"\"\n    Create an instance of the desired transformer based its name.\n\n    Args:\n        name (str): The name of the transformer.\n\n    Returns:\n        An instance of the desired transformer.\n\n    Raises:\n        TrestleError: if the name does not exist in the registry.\n    \"\"\"\n    t = self._transformers.get(name)\n    if t is not None:\n        return t()\n    raise TrestleError(f'Error getting non-registered transform {name}')\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_factory/#trestle.transforms.transformer_factory.TransformerFactory.register_transformer","title":"register_transformer(self, name, transformer)","text":"

                                                                            Register the transformer.

                                                                            This registers transformers in the factory so they may be created by name.

                                                                            Parameters:

                                                                            Name Type Description Default name str

                                                                            The name of the transformer.

                                                                            required transformer TransformerBase

                                                                            The transformer class to be registered.

                                                                            required

                                                                            Returns:

                                                                            Type Description None

                                                                            None

                                                                            Source code in trestle/transforms/transformer_factory.py
                                                                            def register_transformer(self, name: str, transformer: Type[TransformerBase]) -> None:\n\"\"\"\n    Register the transformer.\n\n    This registers transformers in the factory so they may be created by name.\n\n    Args:\n        name (str): The name of the transformer.\n        transformer (TransformerBase): The transformer class to be registered.\n\n    Returns:\n        None\n    \"\"\"\n    self._transformers[name] = transformer\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/","title":"transformer_helper","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper","title":"trestle.transforms.transformer_helper","text":"

                                                                            Transformer helper functions.

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper-classes","title":"Classes","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting","title":" PropertyAccounting ","text":"

                                                                            Property accounting class.

                                                                            Help transformers do accounting.

                                                                            Each time a new record is processed the transformer calls count_group. For each attribute on that record, the transformer calls count_property. - If the property already exactly exists, then its count is incremented. - Otherwise, a new entry is made and the count for that property is set to 1. When the transformer wants to know if a property (name, value, ns, and class) is common to all records for the group, is_common_property is employed to check that the number of records in the group is equal to the number of duplicates there are for the property. If equal, then the property is common.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            class PropertyAccounting():\n\"\"\"Property accounting class.\n\n    Help transformers do accounting.\n\n    > Each time a new record is processed the transformer calls count_group.\n    > For each attribute on that record, the transformer calls count_property.\n      - If the property already exactly exists, then its count is incremented.\n      - Otherwise, a new entry is made and the count for that property is set to 1.\n    > When the transformer wants to know if a property (name, value, ns, and class)\n      is common to all records for the group, is_common_property is employed to check\n      that the number of records in the group is equal to the number of duplicates\n      there are for the property. If equal, then the property is common.\n    \"\"\"\n\n    def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n        self._group_map: Dict[str, int] = {}\n        self._property_map: Dict[str, Dict[str, int]] = {}\n\n    def count_group(self, group: Optional[str] = None) -> None:\n\"\"\"Group accounting.\"\"\"\n        if not group:\n            raise TrestleError('count_group created with group=None')\n        if group not in self._group_map:\n            self._group_map[group] = 0\n        self._group_map[group] += 1\n\n    def count_property(\n        self,\n        group: str,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> None:\n\"\"\"Property accounting.\"\"\"\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if group not in self._property_map:\n            self._property_map[group] = {}\n        if key not in self._property_map[group]:\n            self._property_map[group][key] = 0\n        self._property_map[group][key] += 1\n\n    def is_common_property(\n        self,\n        group: str,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> bool:\n\"\"\"Check for common property.\"\"\"\n        rval = False\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if group in self._group_map and key in self._property_map[group]:\n            rval = self._group_map[group] == self._property_map[group][key]\n        return rval\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.__init__","title":"__init__(self) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def __init__(self) -> None:\n\"\"\"Initialize.\"\"\"\n    self._group_map: Dict[str, int] = {}\n    self._property_map: Dict[str, Dict[str, int]] = {}\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.count_group","title":"count_group(self, group=None)","text":"

                                                                            Group accounting.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def count_group(self, group: Optional[str] = None) -> None:\n\"\"\"Group accounting.\"\"\"\n    if not group:\n        raise TrestleError('count_group created with group=None')\n    if group not in self._group_map:\n        self._group_map[group] = 0\n    self._group_map[group] += 1\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.count_property","title":"count_property(self, group, name=None, value=None, class_=None, ns=None)","text":"

                                                                            Property accounting.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def count_property(\n    self,\n    group: str,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> None:\n\"\"\"Property accounting.\"\"\"\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if group not in self._property_map:\n        self._property_map[group] = {}\n    if key not in self._property_map[group]:\n        self._property_map[group][key] = 0\n    self._property_map[group][key] += 1\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyAccounting.is_common_property","title":"is_common_property(self, group, name=None, value=None, class_=None, ns=None)","text":"

                                                                            Check for common property.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def is_common_property(\n    self,\n    group: str,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> bool:\n\"\"\"Check for common property.\"\"\"\n    rval = False\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if group in self._group_map and key in self._property_map[group]:\n        rval = self._group_map[group] == self._property_map[group][key]\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager","title":" PropertyManager ","text":"

                                                                            Property manager class.

                                                                            Help transformer manage properties.

                                                                            Use materialize to: fetch a property from cache (if caching), else create a new property instance and keep in cache (if caching). Use put_common_property to: keep common properties for each group. Use get_common_properties to: recall the list of common properties for the group.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            class PropertyManager():\n\"\"\"Property manager class.\n\n    Help transformer manage properties.\n\n    > Use materialize to: fetch a property from cache (if caching), else create a new\n      property instance and keep in cache (if caching).\n    > Use put_common_property to: keep common properties for each group.\n    > Use get_common_properties to: recall the list of common properties for the group.\n    \"\"\"\n\n    def __init__(self, caching: bool = True, checking: bool = False) -> None:\n\"\"\"Initialize.\"\"\"\n        self._caching = caching\n        self._checking = checking\n        self._requests = 0\n        self._hits = 0\n        self._map_unique: Dict[str, Any] = {}\n        self._map_common: Dict[str, Dict[str, Property]] = {}\n\n    @property\n    def requests(self) -> int:\n\"\"\"Cache requests.\"\"\"\n        return self._requests\n\n    @property\n    def hits(self) -> int:\n\"\"\"Cache hits.\"\"\"\n        return self._hits\n\n    def materialize(\n        self,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> Property:\n\"\"\"Get property from cache or create new property.\"\"\"\n        self._requests += 1\n        # try fetch from cache\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if key in self._map_unique:\n            self._hits += 1\n            return self._map_unique[key]\n        # create new property and put into cache if caching\n        prop = self._create(name=name, value=value, class_=class_, ns=ns)\n        if self._caching:\n            self._map_unique[key] = prop\n        return prop\n\n    def put_common_property(\n        self,\n        group: Optional[str] = None,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> None:\n\"\"\"Remember common property.\"\"\"\n        if not group:\n            raise TrestleError('put_common_property created with group=None')\n        if group not in self._map_common:\n            self._map_common[group] = {}\n        key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n        if key not in self._map_common[group]:\n            prop = self.materialize(name, value, class_, ns)\n            self._map_common[group][key] = prop\n\n    def get_common_properties(self, group: Optional[str] = None) -> Optional[List[Property]]:\n\"\"\"Recall common properties for the group.\"\"\"\n        rval = None\n        if not group:\n            raise TrestleError('get_common_properties created with group=None')\n        if group in self._map_common:\n            rval = list(self._map_common[group].values())\n        return rval\n\n    def _create(\n        self,\n        name: Optional[str] = None,\n        value: Optional[str] = None,\n        class_: Optional[str] = None,\n        ns: Optional[str] = None\n    ) -> Property:\n\"\"\"Create new property.\"\"\"\n        if self._checking:\n            return Property(name=name, value=value, class_=class_, ns=ns)  # type: ignore\n        return Property.construct(name=name, value=value, class_=class_, ns=ns)  # type: ignore\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager-attributes","title":"Attributes","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.hits","title":"hits: int property readonly","text":"

                                                                            Cache hits.

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.requests","title":"requests: int property readonly","text":"

                                                                            Cache requests.

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.__init__","title":"__init__(self, caching=True, checking=False) special","text":"

                                                                            Initialize.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def __init__(self, caching: bool = True, checking: bool = False) -> None:\n\"\"\"Initialize.\"\"\"\n    self._caching = caching\n    self._checking = checking\n    self._requests = 0\n    self._hits = 0\n    self._map_unique: Dict[str, Any] = {}\n    self._map_common: Dict[str, Dict[str, Property]] = {}\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.get_common_properties","title":"get_common_properties(self, group=None)","text":"

                                                                            Recall common properties for the group.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def get_common_properties(self, group: Optional[str] = None) -> Optional[List[Property]]:\n\"\"\"Recall common properties for the group.\"\"\"\n    rval = None\n    if not group:\n        raise TrestleError('get_common_properties created with group=None')\n    if group in self._map_common:\n        rval = list(self._map_common[group].values())\n    return rval\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.materialize","title":"materialize(self, name=None, value=None, class_=None, ns=None)","text":"

                                                                            Get property from cache or create new property.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def materialize(\n    self,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> Property:\n\"\"\"Get property from cache or create new property.\"\"\"\n    self._requests += 1\n    # try fetch from cache\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if key in self._map_unique:\n        self._hits += 1\n        return self._map_unique[key]\n    # create new property and put into cache if caching\n    prop = self._create(name=name, value=value, class_=class_, ns=ns)\n    if self._caching:\n        self._map_unique[key] = prop\n    return prop\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.PropertyManager.put_common_property","title":"put_common_property(self, group=None, name=None, value=None, class_=None, ns=None)","text":"

                                                                            Remember common property.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def put_common_property(\n    self,\n    group: Optional[str] = None,\n    name: Optional[str] = None,\n    value: Optional[str] = None,\n    class_: Optional[str] = None,\n    ns: Optional[str] = None\n) -> None:\n\"\"\"Remember common property.\"\"\"\n    if not group:\n        raise TrestleError('put_common_property created with group=None')\n    if group not in self._map_common:\n        self._map_common[group] = {}\n    key = _segment_separator.join([str(name), str(value), str(class_), str(ns)])\n    if key not in self._map_common[group]:\n        prop = self.materialize(name, value, class_, ns)\n        self._map_common[group][key] = prop\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.TransformerHelper","title":" TransformerHelper ","text":"

                                                                            OSCAL transformer helper.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            class TransformerHelper():\n\"\"\"OSCAL transformer helper.\"\"\"\n\n    def remove_common_observation_properties(self, observations: List[Observation]) -> List[Property]:\n\"\"\"Remove common observation properties.\"\"\"\n        common_props = []\n        props = {}\n        # count each property occurrence in each observation\n        props_occurrence_counts = self._get_property_occurrence_counts(observations)\n        # remove common properties from observation\n        for key in props_occurrence_counts.keys():\n            # skip property if not identical for each and every observation\n            if props_occurrence_counts[key] != len(observations):\n                continue\n            # remove property from each observation and keep one instance\n            for observation in observations:\n                for prop in as_list(observation.props):\n                    if key == f'{prop.name}:{prop.value}:{prop.class_}':\n                        props[key] = prop\n                        observation.props.remove(prop)\n                        break\n        # formulate list of removed properties\n        for key in props.keys():\n            common_props.append(props[key])\n        # return list of removed properties\n        return common_props\n\n    def _get_property_occurrence_counts(self, observations: List[Observation]) -> Dict[str, Property]:\n\"\"\"Count each property occurrence in each observation.\"\"\"\n        property_occurences = {}\n        for observation in observations:\n            for prop in observation.props:\n                key = f'{prop.name}:{prop.value}:{prop.class_}'\n                if key not in property_occurences.keys():\n                    property_occurences[key] = 0\n                property_occurences[key] += 1\n        return property_occurences\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.TransformerHelper-methods","title":"Methods","text":""},{"location":"api_reference/trestle.transforms.transformer_helper/#trestle.transforms.transformer_helper.TransformerHelper.remove_common_observation_properties","title":"remove_common_observation_properties(self, observations)","text":"

                                                                            Remove common observation properties.

                                                                            Source code in trestle/transforms/transformer_helper.py
                                                                            def remove_common_observation_properties(self, observations: List[Observation]) -> List[Property]:\n\"\"\"Remove common observation properties.\"\"\"\n    common_props = []\n    props = {}\n    # count each property occurrence in each observation\n    props_occurrence_counts = self._get_property_occurrence_counts(observations)\n    # remove common properties from observation\n    for key in props_occurrence_counts.keys():\n        # skip property if not identical for each and every observation\n        if props_occurrence_counts[key] != len(observations):\n            continue\n        # remove property from each observation and keep one instance\n        for observation in observations:\n            for prop in as_list(observation.props):\n                if key == f'{prop.name}:{prop.value}:{prop.class_}':\n                    props[key] = prop\n                    observation.props.remove(prop)\n                    break\n    # formulate list of removed properties\n    for key in props.keys():\n        common_props.append(props[key])\n    # return list of removed properties\n    return common_props\n
                                                                            "},{"location":"api_reference/trestle.transforms.transformer_singleton/","title":"transformer_singleton","text":"

                                                                            handler: python

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_singleton/#trestle.transforms.transformer_singleton","title":"trestle.transforms.transformer_singleton","text":"

                                                                            Create the singleton transformer factory here.

                                                                            "},{"location":"api_reference/trestle.transforms.transformer_singleton/#trestle.transforms.transformer_singleton.transformer_factory","title":"transformer_factory","text":""},{"location":"contributing/DCO/","title":"Developer Certificate of Originality","text":"
                                                                            Developer Certificate of Origin\nVersion 1.1\n\nCopyright (C) 2004, 2006 The Linux Foundation and its contributors.\n660 York Street, Suite 102,\nSan Francisco, CA 94110 USA\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\n\nDeveloper's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n(a) The contribution was created in whole or in part by me and I\nhave the right to submit it under the open source license\nindicated in the file; or\n\n(b) The contribution is based upon previous work that, to the best\nof my knowledge, is covered under an appropriate open source\nlicense and I have the right under that license to submit that\nwork with modifications, whether created in whole or in part\nby me, under the same open source license (unless I am\npermitted to submit under a different license), as indicated\nin the file; or\n\n(c) The contribution was provided directly to me by some other\nperson who certified (a), (b) or (c) and I have not modified\nit.\n\n(d) I understand and agree that this project and the contribution\nare public and that a record of the contribution (including all\npersonal information I submit with it, including my sign-off) is\nmaintained indefinitely and may be redistributed consistent with\nthis project or the open source license(s) involved.\n
                                                                            "},{"location":"contributing/github_actions_setup/","title":"Github actions setup","text":"

                                                                            Github actions contains variables which have opaque values to a user. The variables are documented here such that trestle can be setup on a fork etc.

                                                                            "},{"location":"contributing/github_actions_setup/#secrets","title":"Secrets","text":"
                                                                            • ADMIN_PAT: Github PAT with sufficient write access to merge content into develop and commit to gh-pages and main

                                                                            • SONAR_TOKEN: Token to sonarcloud with rights to the appropriate project.

                                                                            "},{"location":"contributing/github_actions_setup/#repository-level-variables","title":"Repository level variables","text":"
                                                                            • PYTHON_MIN: Minimum test version of python e.g. 3.9
                                                                            • PYTHON_MAX: Maxmimum test version of python e.g. 3.11
                                                                            "},{"location":"contributing/github_actions_setup/#authorization-with-pypi","title":"Authorization with pypi","text":"

                                                                            Pypi authorization must be setup following the procedure in the following documents

                                                                            • https://docs.pypi.org/trusted-publishers/adding-a-publisher/
                                                                            "},{"location":"contributing/mkdocs_contributing/","title":"Contributing overview","text":""},{"location":"contributing/mkdocs_contributing/#contributing-in-general","title":"Contributing In General","text":"

                                                                            Our project welcomes external contributions. If you have an itch, please feel free to scratch it.

                                                                            To contribute code or documentation, please submit a pull request.

                                                                            A good way to familiarize yourself with the codebase and contribution process is to look for and tackle low-hanging fruit in the issue tracker. Before embarking on a more ambitious contribution, please quickly get in touch with us.

                                                                            Note: We appreciate your effort, and want to avoid a situation where a contribution requires extensive rework (by you or by us), sits in backlog for a long time, or cannot be accepted at all!

                                                                            "},{"location":"contributing/mkdocs_contributing/#proposing-new-features","title":"Proposing new features","text":"

                                                                            If you would like to implement a new feature, please raise an issue labelled enhancement before sending a pull request so the feature can be discussed. This is to avoid you wasting your valuable time working on a feature that the project developers are not interested in accepting into the code base.

                                                                            "},{"location":"contributing/mkdocs_contributing/#fixing-bugs","title":"Fixing bugs","text":"

                                                                            If you would like to fix a bug, please raise an issue labelled bug before sending a pull request so it can be tracked.

                                                                            "},{"location":"contributing/mkdocs_contributing/#merge-approval","title":"Merge approval","text":"

                                                                            The project maintainers use LGTM (Looks Good To Me) in comments on the code review to indicate acceptance. A change requires LGTMs from one of the maintainers.

                                                                            For a list of the maintainers, see the maintainers page.

                                                                            "},{"location":"contributing/mkdocs_contributing/#trestle-merging-and-release-workflow","title":"Trestle merging and release workflow","text":"

                                                                            trestle is operating on a simple, yet opinionated, method for continuous integration. It's designed to give developers a coherent understanding of the objectives of other past developers. The criteria for this are below. Trestle effectively uses a gitflow workflow with one modification: PR's merge into develop are squash merged as one commit.

                                                                            In trestle's CI environment this results in the following rules:

                                                                            1. All Commit's MUST be signed off with git commit --signoff irrespective of the author's affiliation. This ensures all code can be attributed.
                                                                            2. This is enforced by DCO bot and can be overrided by maintainers presuming at least one commit is signed-off.
                                                                            3. All commits SHOULD use conventional commits
                                                                            4. This is as github, when only one commit is in a PR, will use the native git commit message as the merge commit title.
                                                                              1. When only a single commit is provided the commit MUST be an conventional commit and will be checked the Lint PR aciton.
                                                                            5. All PR's title's MUST be formed as an convention commit
                                                                            6. This is checked by the Lint PR action
                                                                            7. All PR's to develop and hotfix PR's to main must close at least one issue by linking the PR to an issue.
                                                                            8. Trestle will release on demand the default approach for a hot fix should be to merge into develop, followed by releasing to main, unless this will release functionality that is not ready.
                                                                            9. Each feature/fix/chore (PR into develop) be represented by a single commit into develop / main with a coherent title (in the PR).
                                                                            10. The trestle preference for doing this is to use squash merge functionality when merging a PR into develop.
                                                                            11. Developers MUST pass the required CI checks for each PR.
                                                                            12. Developers are encouraged to use GitHub's automated merge process where possible to keep the number of active PR's low.
                                                                            "},{"location":"contributing/mkdocs_contributing/#merge-details-for-committers","title":"Merge details for committers:","text":"
                                                                            1. All merges into develop MUST be conducted by a squash-merge
                                                                            2. All merges from develop into main MUST be done by a merge commit (e.g. preserving the history of commits into the develop branch).
                                                                            3. Hotfixes into main, not via develop, MUST be done via a squash merge.
                                                                            4. Merge's into any branch excluding main and develop are at the developers choice.
                                                                            5. Use of autocommit is encouraged to ensure commit messages and squash vs merge commit are completed properly.
                                                                            "},{"location":"contributing/mkdocs_contributing/#working-from-a-fork","title":"Working from a fork","text":"
                                                                            1. In order not to break Github Actions security model SonarCloud will not run on a fork.
                                                                            2. Given this a maintainer MAY determine that sonar needs to be run and ask you to first merge your branch to a staging branch, after reviewing for security risks in the CI pipeline.
                                                                            3. From this staging branch sonar would be run and then the code merged.
                                                                            "},{"location":"contributing/mkdocs_contributing/#typing-docstrings-and-documentation","title":"Typing, docstrings and documentation","text":"

                                                                            trestle has a goal of using PEP 484 type annotations where possible / practical. The devops process does not strictly enforce typing, however, the expectation is that type coverage is added for new commits with a focus on quality over quantity (e.g. don't add Any everywhere just to meet coverage requirements). Python typing of functions is an active work in progress.

                                                                            mkbuild is used to generate the trestle documenation site. The mkbuild website includes an API reference section generated from the code. Docstrings within the code are expected to follow google style docstrings.

                                                                            "},{"location":"contributing/mkdocs_contributing/#legal","title":"Legal","text":"

                                                                            Each source file must include a license header for the Apache Software License 2.0. Using the SPDX format is the simplest approach. e.g.

                                                                            # Copyright (c) 2020 IBM Corp. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n

                                                                            We have tried to make it as easy as possible to make contributions. This applies to how we handle the legal aspects of contribution. We use the same approach - the Developer's Certificate of Origin 1.1 (DCO) - that the Linux\u00ae Kernel community uses to manage code contributions.

                                                                            We simply ask that when submitting a patch for review, the developer must include a sign-off statement in the commit message.

                                                                            Here is an example Signed-off-by line, which indicates that the submitter accepts the DCO:

                                                                            Signed-off-by: John Doe <john.doe@example.com>\n

                                                                            You can include this automatically when you commit a change to your local git repository using the following command:

                                                                            git commit --signoff\n

                                                                            Note that DCO signoff is enforced by DCO bot. Missing DCO's will be required to be rebased with a signed off commit before being accepted.

                                                                            "},{"location":"contributing/mkdocs_contributing/#setup-developing-trestle","title":"Setup - Developing trestle","text":""},{"location":"contributing/mkdocs_contributing/#does-trestle-run-correctly-on-my-platform","title":"Does trestle run correctly on my platform","text":"
                                                                            • (Optional) setup a venv for python
                                                                            • Run make develop
                                                                            • This will install all python dependencies
                                                                            • It will also checkout the submodules required for testing.
                                                                            • Run make test
                                                                            • This should run on all platforms
                                                                            "},{"location":"contributing/mkdocs_contributing/#setting-up-vscode-for-python","title":"Setting up vscode for python.","text":"
                                                                            • Use the following commands to setup python:
                                                                            python3 -m venv venv\n. ./venv/bin/activate\n# for zsh put .[dev] in quotes as below\npip install -q -e \".[dev]\" --upgrade --upgrade-strategy eager\n
                                                                            • Install vscode plugin Python extension for Visual Studio Code

                                                                            • Enable yapf for code formatting

                                                                            • Enable flake8 for code linting

                                                                            "},{"location":"contributing/mkdocs_contributing/#testing-python-in-vscode","title":"Testing python in vscode","text":"

                                                                            Tests should be in the test subdirectory. Each file should be named test_*.py and each test function should be named *_test().

                                                                            Note that with Python3 there should be no need for init.py in directories.

                                                                            Test discovery should be automatic when you select a .py file for editing. After tests are discovered a flask icon will appear on the left and you can select it to see a panel listing of your tests. In addition your test functions will be annotated with Run/Debug so they can be launched directly from the editor. When everything is set up properly you should be able to step through your test code - which is important.

                                                                            Sometimes the discovery fails - and you may need to resort to uninstalling the python extension and reinstalling it - perhaps also shutting down code and restarting. This is a lightweight operation and seems to be safe and usually fixes any problems.

                                                                            Test disovery will fail or stop if any of the tests have errors in them - so be sure to monitor the Problems panel at the bottom for problems in the code.

                                                                            Note that there are many panels available in Output - so be sure to check Python Test Log for errors and output from the tests.

                                                                            pytest fixtures are available to allow provision of common functionality. See conftest.py and tmp_dir for an example.

                                                                            "},{"location":"contributing/mkdocs_contributing/#nist-reference-data-for-testing","title":"NIST reference data for testing.","text":"

                                                                            Trestle relies on reference data from two NIST repositories for testing:

                                                                            • https://github.com/usnistgov/OSCAL
                                                                            • https://github.com/usnistgov/oscal-content

                                                                            Both of these repositories are submodules in the trestle project. In order to develop / test trestle the submodules must be checked out with git submodule update --init or make submodules.

                                                                            "},{"location":"contributing/mkdocs_contributing/#code-style-and-formating","title":"Code style and formating","text":"

                                                                            trestle uses yapf for code formatting and flake8 for code styling. It also uses pre-commit hooks that are integrated into the development process and the CI. When you run make develop you are ensuring that the pre-commit hooks are installed and updated to their latest versions for this repository. This ensures that all delivered code has been properly formatted and passes the linter rules. See the pre-commit configuration file for details on yapf and flake8 configurations.

                                                                            Since yapf and flake8 are installed as part of the pre-commit hooks, running yapf and flake8 manually must be done through pre-commit. See examples below:

                                                                            make code-format\nmake code-lint\n

                                                                            ...will run yapf and flake8 on the entire repo and is equivalent to:

                                                                            pre-commit run yapf --all-files\npre-commit run flake8 --all-files\n

                                                                            ...and when looking to limit execution to a subset of files do similar to:

                                                                            pre-commit run yapf --files trestle/*\npre-commit run flake8 --files trestle/*\n

                                                                            Note that in both of these cases autogenerated files under trestle/oscal are excluded. Note that for IDE support setup.cfg maintains a cache of flake8 configuration.

                                                                            "},{"location":"contributing/mkdocs_contributing/#developers-guide-to-trestle-upgrade-commensurate-with-oscal-models-upgrade","title":"Developers Guide to trestle upgrade commensurate with OSCAL models upgrade","text":"

                                                                            This is a general guide on how to go about upgrading compliance-trestle to support a new version of OSCAL models.

                                                                            The steps are as follows:

                                                                            1. Create in GitHub repo (remote)
                                                                            2. Clone upgrade branch into /trestle-upgrade folder (local <- remote)
                                                                            3. Download revised and new OSCAL models into folder /trestle-upgrade/release-schemas (local <- remote)
                                                                              • See https://github.com/usnistgov/OSCAL/releases
                                                                              • Create & source python virtual environment venv.trestle-upgrade (local)
                                                                              • Orient current folder to /trestle-upgrade (local)
                                                                              • Run make develop (local)
                                                                              • Make necessary code changes:
                                                                                • Run python scripts/gen_oscal.py (local)
                                                                                • Run make test-all (local)
                                                                                • Fix errors and failures via modification of code generation modules and existing trestle modules, as appropriate case-by-case (local)
                                                                                • Repeat until all errors and failures are fixed (local)
                                                                                • Run make code-format (local)
                                                                                • Run make code-lint (local)
                                                                                • Push /trestle-upgrade folder changes back to GitHub repo (local -> remote)
                                                                                • Create PR for trestle-upgrade branch -> develop branch (remote)
                                                                                • Get PR approval (remote)
                                                                                • Merge PR into develop branch (remote)
                                                                                • Create PR for develop branch -> main branch (remote)
                                                                                • Create breaking change (remote)
                                                                                • Get PR approval (remote)
                                                                                • Merge develop branch into main branch (remote)"},{"location":"contributing/mkdocs_contributing/#overview-of-process-to-take-oscal-models-and-upgrade-trestle-python-code","title":"Overview of process to take OSCAL models and upgrade trestle Python code","text":""},{"location":"contributing/plugins/","title":"Adding plugins to trestle","text":"

                                                                                  Trestle provides a mechanism for 3rd party providers to extend its command interface via a plugin architecture. All trestle plugins that conforms to this specification will be automatically discovered by trestle if installed, and their command(s) will be added to trestle sub-commands list. Below we describe this plugin mechanism with the help of an example plugin compliance-trestle-fedramp that we created as a separate python project that can be installed via pip.

                                                                                  "},{"location":"contributing/plugins/#create-the-trestle-plugin-proejct","title":"Create the trestle plugin proejct","text":"

                                                                                  A separate plugin project needs to be created that will conatin the code for plugin and its commands. This plugin can be given any name and should be available for installation via pip. For example, we created a plugin project called compliance-trestle-fedramp which can be installed as pip install compliance-trestle-fedramp. The project name doesn't need to start with compliance-trestle.

                                                                                  "},{"location":"contributing/plugins/#project-organization","title":"Project Organization","text":"

                                                                                  The plugin project should be organized as shown below.

                                                                                  compliance-trestle-fedramp\n\u251c\u2500\u2500 trestle_fedramp\n\u2502   \u251c\u2500\u2500 __init.py__\n\u2502   \u251c\u2500\u2500 commands\n|   |   \u251c\u2500\u2500 __init.py__\n|   |   \u251c\u2500\u2500 validate.py\n\u2502   \u251c\u2500\u2500 <other source files or folder>\n\u251c\u2500\u2500 <other files or folder>\n

                                                                                  Trestle uses a naming convention to discover the top-level module of the plugin projects. It expects the top-level module to be named trestle_{plugin_name}. This covention must be followed by plugins to be discoverable by trestle. In the above example, the top-level module is named as trestle_fedramp so that it can be autmatically discovered by trestle. All the python source files should be created inside this module (folder).

                                                                                  The top-evel module should contain a commands directory where all the plugin command files should be stored. Each command should have its own python file. In the above exaample, validate.py file conatins one command for this plugin. Other python files or folders should be created in the top-level module folder, outside the commands folder. This helps in keeping the commands separate and in their discovery by trestle.

                                                                                  "},{"location":"contributing/plugins/#command-creation","title":"Command Creation","text":"

                                                                                  The plugin command should be created as shown in the below code snippet.

                                                                                  from trestle.core.commands.command_docs import CommandBase\nfrom trestle.core.commands.command_docs import CommandPlusDocs\n\nclass ValidateCmd(CommandBase):\n\"\"\"Validate contents of an OSCAL model based on FedRAMP specifications.\"\"\"\n\n    name = 'fedramp-validate'\n\n    def _init_arguments(self) -> None:\n        logger.debug('Init arguments')\n        self.add_argument('-f', '--file', help='OSCAL file to validate.', type=str, required=True)\n\n        self.add_argument(\n            '-o', '--output-dir', help='Output directory for validation results.', type=str, required=True\n        )\n\n    def _run(self, args: argparse.Namespace) -> int:\n        model_file = pathlib.Path(args.file).resolve()\n\n        output_dir = pathlib.Path(args.output_dir).resolve()\n        ...\n        ...\n        return 0 if valid else 1\n

                                                                                  There should be a command class for example, ValidateCmd which should either extend from CommandBase or CommandPlusDocs. Trestle uses ilcli package to create commands. CommandBase extends from ilcli.Command that initializes the command including help messages and input parameters. CommandPlusDocs in turn extends from CommandBase. The difference between CommandBase and CommandPLusDocs is that CommandBase does not require command line parameter trestle-root to be set or the current directory to be a valid trestle root, whereas CommandPlusDocs requires a valid trestle-root and checks for it. Hence, depending upon the requirement of the plugin command it can extend from either of these classes.

                                                                                  The docstring of the command class is used as the help message for the command. Input arguments to the command should be specified in _init_arguments method as shown above. The acutal code of the command is contained in_run method. This method is called by ilcli when the command is excuted on the commandline. The command arguments can be accessed from the args input parameter as shown above. The command should return 0 in case of successful execution, or any number greater than 0 in case of failure. Please see trestle.core.commands.common.return_codes.CmdReturnCodes class for specific return codes in case of failure.

                                                                                  The command class should conatin the name field which should be set to the desired command name. In the above example, the command is called fedramp-validate. This name is automatically added to the list of sub-command names of trestle during the plugin discovery process. This command can then be invoked as trestle {name} from the commandline e.g., trestle fedramp-validate. Any input parameters to the command can also be passed on the commandline after the command name.

                                                                                  "},{"location":"contributing/trestle_oscal_object_model/","title":"Using trestle as an object model for OSCAL","text":"

                                                                                  Trestle provides an object model for OSCAL to ease the development and validation of OSCAL objects that reside in the trestle.oscal module. This functionality, which is built on pydantic and python data classes, allows validation of the OSCAL schema and is leveraged to provide a variety of utility functions including:

                                                                                  • IO Support for yaml / json / python dict serialisation see OscalBaseModel for trestle enhancements
                                                                                  • The ability to generate pro-forma objects using trestle.core.generate::generate_sample_model
                                                                                  • Integration into the flask api framework (demo)
                                                                                  "},{"location":"contributing/trestle_oscal_object_model/#mapping-and-variance-with-oscal-names","title":"Mapping and variance with OSCAL names.","text":"

                                                                                  The underlying object model that trestle relies on is the json schema published by NIST here. In understanding these models the model reference page is an indispensable source.

                                                                                  When generating the python data class based models we have tried to be as faithful as we can to the naming convention provided by OSCAL. This is the hierarchy of rules that we have used:

                                                                                  1. Do not include prepends from the json schema (e.g. assembly_oscal-catalog_catalog becomes the short name catalog), modules are used for scoping statements
                                                                                  2. OSCAL modules use hyphen case (e.g. system-security-plan) and this is converted to CamelCase (e.g. SystemSecurityPlan)
                                                                                  3. Name collisions with reserved words in python are post-pended with an underscore (e.g. class becomes class_)
                                                                                  4. If a model is used across multiple OSCAL schemas (e.g. metadata) it is put into the common module(trestle.oscal.common), otherwise it will be scoped to a model specifically for that schema.
                                                                                  5. Any unresolved duplicates are resolved by adding an index e.g. class State1
                                                                                  "},{"location":"contributing/trestle_oscal_object_model/#oscal-schema-mapping","title":"OSCAL Schema mapping","text":"

                                                                                  This maps between OSCAL values and the corresponding pydantic/python data class in trestle. For example, to get a catalog you would call:

                                                                                  from pathlib import Path\nfrom trestle.oscal.catalog import Catalog\n\nmy_catalog = Catalog.oscal_read(Path('path/to/file.json'))\n
                                                                                  Oscal schema json schema name Trestle module Trestle class name Catalog catalog catalog trestle.oscal.catalog Profile profile profile trestle.oscal.profile Component Definition component-definition trestle.oscal.component ComponentDefinition System Security Plan system-security-plan trestle.oscal.ssp SystemSecurityPlan Assessment Plan assessment-plan trestle.oscal.assessment_plan AssessmentPlan Assessment Results assessment-results trestle.oscal.assessment_results AssessmentResults Plan of action and milestones plan-of-action-and-milestones trestle.oscal.poam PlanOfActionAndMilestones"},{"location":"contributing/website/","title":"Developing for the trestle documentation website","text":"

                                                                                  This page describes the developing for the trestle (website) which is deployed at https://oscal-compass.github.io/compliance-trestle.

                                                                                  "},{"location":"contributing/website/#documentation-for-use-within-the-github-project","title":"Documentation for use within the github project.","text":"

                                                                                  Github uses certain files within a project such as /README.md, /CONTRIBUTING.md, LICENSE which are specifically indexed by github. The current documentation website build reuses some of these files, specifically:

                                                                                  • Contents of README.md
                                                                                  • Entirety of LICENSE
                                                                                  • Entirety of CONTRIBUTING.md
                                                                                  • Entirety of CODE_OF_CONDUCT.md
                                                                                  • Entirety of CHANGELOG.md
                                                                                  • Entirely of MAINTAINERS.md
                                                                                  • Entirely of DCO1.1.txt

                                                                                  For this to work correctly no relative links within the github repository should exist. All links should be absolute to the documentation website.

                                                                                  "},{"location":"contributing/website/#build-system-and-local-testing-of-the-website","title":"Build system and local testing of the website.","text":"

                                                                                  Trestle has adopted the mkdocs system to generate this website using a small number of extensions to mkdocs. The website can be viewed locally from a clone of the compliance-trestle repo by running make docs-serve in the root directory bringing the website up at https://localhost:8000. If you experience issues run make develop to ensure the appropriate markdown extensions are in your python environment.

                                                                                  make docs-serve performs two actions:

                                                                                  • Runs the custom automation script scripts/website_automation.py
                                                                                  • Serves the website on localhost.

                                                                                  All documentation specific assets are stored within the ./docs folder. The exception being mkdocs.yml which configures the documentation tree. Before opening a PR users should ensure:

                                                                                  • No warnings are generated by mkdocs
                                                                                  • All markdown documents within ./docs are included in the website navigation defined in mkdocs.yml
                                                                                  "},{"location":"contributing/website/#trestle-custom-automation","title":"trestle custom automation.","text":"

                                                                                  In order to streamline development, and ensure the website remains up to date, a small automation script has been built. This automation script principally ensures that:

                                                                                  • License is consistent with github.com
                                                                                  • All modules are in the reference documentation

                                                                                  running make docs-automation will ensure that the website is ready to deploy.

                                                                                  "},{"location":"contributing/website/#building-the-models-from-the-oscal-schemas","title":"Building the models from the OSCAL schemas.","text":"

                                                                                  The creation of the OSCAL models in trestle/oscal is a multi-step process:

                                                                                  • The oscal schemas are downloaded as modules from NIST into the nist-source/json/schema directory.
                                                                                  • The script scripts/gen-oscal.py loads each schema file and converts it to pydantic/python with datamodel-codegen.
                                                                                  • The generated python files may need some fixup, so a separate script scripts/fix_any.py is run on each file.
                                                                                  • Note that there is one schema specific to IBM needs and it is loaded from 3rd-party-schema-documents/IBM_target_schema_v1.0.0.json.

                                                                                  The whole process is handled in the Makefile by make code-gen. A normal user would never need to run this but developers may need to, particularly if there are changes to the OSCAL schemas.

                                                                                  Also note that the depenedent tools, pydantic and datamodel-codegen, may get updated by doing a fresh make install or make develop, which may then result in a change to the model files.

                                                                                  "},{"location":"contributing/website/#items-handled-by-fix_anypy","title":"Items handled by fix_any.py.","text":"

                                                                                  The original motivation for this script was to replace numerous situations where the type assigned to a given variable was simply Any, which meant no type enforcement would apply for that variable, defeating the purpose of the strict type enforcement provided by Pydantic. As of this writing the number of such cases has been reduced to just one - which is handled by the script.

                                                                                  Other issues handled by the script are:

                                                                                  • The current OSCAL schemas have situations where objects are defined within different classes in a schema using the same name, but the contents of those classes may or may not be different. datamodel-codegen handles this by creating separate classes as needed and appending 1, 2 etc. to the names, keeping them distinct. The resulting high level classes that reference them behave as expected, but if components of those classes are added in a granular way by a user or developer, the correct index must be used.
                                                                                  • To reduce side-effects of the duplicate classes, classes are checked to see if they are identical or not. If they are identical the separate 1, 2 classes are culled and references to them are pointed to the non-indexed class.
                                                                                  • Currently there are 5 classes that require a separate '1' version: Status, Type, Entry, LocalDefinitions, and Action.
                                                                                  • In order to guarantee there are no induced forward references in the files, the classes are reordered to minimize the need for forwards, and any that can't be avoided are explicitly provided at the bottom of the file.
                                                                                  • The generated files have many classes that simply have a __root__ element defined, along with a description. Such classes don't have particular value in such a simple form and could instead simply be defined in the parent class.
                                                                                  "},{"location":"contributing/website/#seeing-the-changes-induced-by-fix_anypy-on-the-classes","title":"Seeing the changes induced by fix_any.py on the classes.","text":"

                                                                                  As a convenience for developers, a separate script, scripts/order_classes.py is available, which orders the classes in a given file alphabetically. This way, if you use the script on files before and after applying fix_any.py you can use a normal diff tool to see the changes made. This is strictly as a development tool for doing the comparison and the resulting files will not work since they will have forward references.

                                                                                  "},{"location":"plugins/compliance-trestle-fedramp/","title":"compliance-trestle-fedramp plugin","text":"

                                                                                  This plugin provides functionality for validating an SSP for FedRAMP compliance. It provides both an API interface and a trestle command for performing this validation.

                                                                                  "},{"location":"plugins/compliance-trestle-fedramp/#trestle-fedramp-validate","title":"trestle fedramp-validate","text":"

                                                                                  This command allows users to validate existing OSCAL SSP file (in JSON or YAML format) for FedRAMP compliance. For example, trestle fedramp-validate -f /local_dir/ssp.json -o report/ will validate ssp.json file for fedramp complaince and store the validation reports in report folder.

                                                                                  The following options are supported:

                                                                                  • -f or --file: specifies the path of an existing OSCAL SSP file. It may be an absolute or relative path. The file must be in either JSON or YAML format. This is a required option.
                                                                                  • -o or --output: specifies the name of the output directory where the validation reports will be stored. It may be an absolute or relative path. The output directory should already exist. This is also a required option.

                                                                                  The validation reports are created in XML and HTML format and provide details on which part of the SSP are not complaint as per FedRAMP specification.

                                                                                  "},{"location":"reference/third-party-result-schema-SCC/","title":"Schema of Assessment Results for Interchange with IBM Cloud Security and Compliance Center, SCC","text":"

                                                                                  This document depicts the structure and guidelines for creating an OSCAL result object which would be generated by various transformers for different tools such as Tanium to OSCAL and OSCO to OSCAL. Policy Validation Points (PVPs) such as toolchain that directly generate OSCAL results for sending to SCC Exchange API should follow the structure and guidelines described below.

                                                                                  The overall object will be a results element of OSCAL Assessment Result schema wrapped in an outer json object as shown below.

                                                                                  {\n\"results\": [\n{\n\"result\": \"object\"\n},\n{\n\"result\": \"object\"\n}\n]\n}\n

                                                                                  Each result object represents one assessment scan and should have the required properties as per OSCAL schema. The start and end represents the start and end datetime of evidence collection activity. The end is optional. In addition to these, the result object may contain details about inventory, list of observations (checks) for each inventory, and findings for profile level controls (such as NIST).

                                                                                  {\n\"uuid\": \"cd54e9bf-f4d3-45d6-ae3b-6e8255847dc2\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-04-05T20:19:11.000+00:00\",\n\"end\": \"2021-04-05T20:19:11.000+00:00\",\n\"local-definitions\": {},\n\"reviewed-controls\": {},\n\"observations\": {},\n\"findings\": {}\n}\n

                                                                                  The inventory should be included in local-definitions if observations are being reported, but can be omitted if only findings are being reported. As reviewed-controls is required as per OSCAL schema, an empty object should be included if only observations are being reported. Optionally, the controls for which the status is being reported in findings can be captured here. The actual assessment checks being performed on different inventory items should be captured under observations. This can be omitted if only findings are being reported. As findings is required as per OSCAL schema, an empty object can be included if only observations are being reported and no profile controls are being assessed. Otherwise, findings should include the status of profile controls.

                                                                                  "},{"location":"reference/third-party-result-schema-SCC/#general-guidance","title":"General Guidance","text":"
                                                                                  1. All the properties in the source result (tool specific format) should be represented as properties of the right objects in OSCAL such as inventory-items, observations, etc. The properties should have a tool specific namespace to convey that the property names are exactly same as what is coming from specific tools.

                                                                                  2. Not everything from the non-OSCAL results are relevant (required) by SCC. The relevant properties MUST have SCC specific class such as scc_inventory_item_id, scc_result, etc. This will help SCC identify corresponding information from different tools and handle them appropriately. SCC MUST store the original property names so that when these are retrieved by tools later, they can get back the same name-value pairs as was there in the input data.

                                                                                  3. There must be a pre-defined set of properties (class values) from SCC for each result object component such as inventory-items, components, observations, etc.

                                                                                  4. A property value MUST be a string of appropriate format.

                                                                                  "},{"location":"reference/third-party-result-schema-SCC/#transforms","title":"Transforms","text":"
                                                                                  1. File Unification SCC class for OSCO and Tanium to OSCAL.xlsx contains the SCC class mapping from Tanium and OpenShift Compliance Operator results data to OSCAL. Although other properties are constructed during transformation, only items having SCC class are shown in the table.
                                                                                  "},{"location":"reference/third-party-result-schema-SCC/#inventory","title":"Inventory","text":"
                                                                                  1. Inventory is captured under local-definitions in result object. local-definitions can be used to represent inventory items, components, users, etc. For our purposes only components and inventory-items will be used. Components should be used to represent software, services, etc. whereas inventory-items represent specific machines, VMs, network devices, etc. The inventory items should be associated to a component through implemented-components as shown below.
                                                                                  {\n\"local-definitions\": {\n\"components\": {\n\"b3e243a1-4660-4f5a-aa85-159b4b2d69ce\": {\n\"type\": \"Operating System\",\n\"title\": \"Windows 10\",\n\"description\": \"Windows 10\",\n\"status\": {\n\"state\": \"operational\"\n}\n}\n},\n\"inventory-items\": [\n{\n\"uuid\": \"c9fb63cf-d21e-4584-88f8-44d67ea33ba0\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"Computer Name\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"cmp-wn-2106.demo.tanium.local\"\n},\n{\n\"name\": \"Tanium Client IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"192.168.0.120\",\n\"class\": \"scc_inventory_item_id\"\n},\n{\n\"name\": \"IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"['fe80::cd44:4154:61e8:53ae', '192.168.0.120']\"\n},\n{\n\"name\": \"Count\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1\"\n}\n],\n\"implemented-components\": [\n{\n\"component-uuid\": \"b3e243a1-4660-4f5a-aa85-159b4b2d69ce\"\n}\n]\n}\n]\n}\n}\n
                                                                                  1. Inventory items have one required property with class scc_inventory_item_id as shown above. Similarly in some other tool's result the scc_inventory_item_id may be specified through some other property. It is the job of the transformation code to appropriately specify class values for required properties. As shown above, non-mandatory property such as count from native result does not have any class specified.

                                                                                  2. The type of the inventory item is specified by linking it to component via implemented-components.

                                                                                  "},{"location":"reference/third-party-result-schema-SCC/#observation","title":"Observation","text":"
                                                                                  1. Loosely speaking, an observation object equates with results from a goal check, and the observation is uniquely identified by a uuid, e.g.,
                                                                                  {\n\"uuid\": \"00000000-0000-4000-9999-000000000016\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\"\n}\n
                                                                                  1. A sample observation object generated from Tanium result looks like -
                                                                                  {\n\"uuid\": \"74b605f8-7e8c-41b3-9514-2412692fbe01\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-11T22:34:03+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"c8919d2b-3300-4f3f-98f6-15a7104c2e04\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-11T22:34:03.000+00:00\"\n}\n
                                                                                  1. An observation has five required properties -

                                                                                  2. scc_predefined_profile - identifies both Goal based Profiles (eg CIS-benchmarks, IBM BP etc) and Control/Regulation based Profiles (eg. NIST, FS Cloud etc). The way the integrators or customers will differentiate between the two types of profiles is by the OSCAL element used i.e., Goal based Profiles are defined in the observation element which carries the goal id (check id) and posture. Control/Regulation based Profiles\u00a0 are defined in the finding element which carries the control posture, the custom profile name, and the mapping of the goal results to NIST controls

                                                                                  3. scc_check_version, scc_predefined_profile_version - gives the version of the goal/profile i.e., CIS benchmark version used for check.
                                                                                  4. scc_goal_description, scc_check_name_id - gives the specific goal check (rule) that was assessed from the scc_predefined_profile.
                                                                                  5. scc_result - gives the outcome of performing the check. Possible values are - \"pass\", \"fail\", \"error\" , \"unknown\", \"notchecked\", \"notapplicable\".
                                                                                  6. scc_timestamp - datetime for this observation. This can be date and time when this observation was performed or reported.

                                                                                  7. Targets such as systems or services MUST be a subject in the observation, which MUST be identified by a uuid-ref value pointing to the subject in local-definitions.

                                                                                  "},{"location":"reference/third-party-result-schema-SCC/#finding","title":"Finding","text":"
                                                                                  1. A finding represents the assessment of a profile control such as NIST 800-53: AC-1 and the related observations. A sample finding object looks like -
                                                                                  {\n\"uuid\": \"cde35fad-3922-4046-8ef8-830e77ffd75a\",\n\"title\": \"800-53: IA-5\",\n\"description\": \"800-53: IA-5\",\n\"target\": {\n\"type\": \"statement-id\",\n\"id-ref\": \"800-53: IA-5\",\n\"props\": [\n{\n\"name\": \"Profile\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Windows 10 - NIST 800-53\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"version: 1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Custom ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"800-53: IA-5\"\n}\n],\n\"status\": \"not-satisfied\"\n},\n\"related-observations\": [\n{\n\"observation-uuid\": \"d8bd1785-b95f-45c9-9fa8-32a362845102\"\n},\n{\n\"observation-uuid\": \"d06c6f13-5006-4e2d-b3f3-5cdb577473b1\"\n}\n]\n}\n
                                                                                  1. A finding has two required property scc_predefined_profile that gives the name of the profile whose control is specified in \"id-ref\", and scc_predefined_profile_version.

                                                                                  2. If there is no finding associated with a PVP, a single finding will be created (to preserve valid OSCAL) where the UUID maps to a 'all zeros' UUID e.g.:

                                                                                  {\n\"uuid\": \"00000000-0000-4000-8000-000000000000\",\n\"title\": \"No finding\",\n\"description\": \"No finding.\"\n}\n
                                                                                  "},{"location":"tutorials/trestle_sample_workflow/","title":"Tutorial: Introduction to trestle workflow","text":"

                                                                                  Here are step-by-step instructions to manipulate a NIST standard OSCAL catalog using the compliance-trestle (\"trestle\") tool.

                                                                                  "},{"location":"tutorials/trestle_sample_workflow/#objective","title":"Objective","text":"

                                                                                  Learn how to split and merge an OSCAL catalog json file using trestle commands and its command line interface (CLI). Trestle simplifies the manipulation and management of large OSCAL documents by allowing controlled deconstruction into smaller components, and later reconstruction after editing those components. And all operations guarantee that the individual files conform to the corresponding OSCAL schema to maintain integrity of the document in the process.

                                                                                  This tutorial assumes you have installed Python and installed trestle in a virtual environment per the directions found here.

                                                                                  The examples shown will work for linux and mac, but Windows will require the following modifications:

                                                                                  • use backslashes `\\` for file paths (this is optional in most cases)
                                                                                  • use copy instead of cp (unless you have cp installed)
                                                                                  • use md instead of mkdir (unless you have mkdir installed)
                                                                                  • quotes (') are often not needed unless the text includes spaces, but if quotes are needed they should be double quotes (\")

                                                                                    Commands are shown without prompts so they are easy to cut and paste, and responses by trestle are shown with >>> at the start of the line. In actual usage the >>> would not appear.

                                                                                    Be sure to include the quotes (' ') as shown in the examples, e.g. merge -e 'catalog.*' [On windows you should probably use double quotes (\") as needed.]

                                                                                    In this tutorial you will see sections that contain dropdown that is revealed when you click on them. Below is an example (\"Like this\"). Be sure to click on those sections to see their contents - and then close them if you like.

                                                                                    Like this
                                                                                    more\ninformation\nin\nhere\n

                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#step-1-create-a-trestle-workspace-if-you-dont-have-one-already","title":"Step 1: Create a trestle workspace if you don't have one already","text":"
                                                                                    mkdir my_workspace\ncd my_workspace\ntrestle init\n>>> Initialized trestle project successfully in [user_path]/my_workspace\n
                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#step-2-import-a-catalog-from-the-trestle-sample-data-directory-into-your-trestle-workspace","title":"Step 2: Import a catalog from the trestle sample data directory into your trestle workspace","text":"

                                                                                    For this tutorial we will use a catalog file from NIST, but we first must import it into the trestle workspace. This can be done either by first downloading the file locally and then importing it, or you can download it directly using its url address.

                                                                                    We will import the file directly from the NIST OSCAL github site. The specific catalog is NIST_SP-800-53_rev5_catalog.json

                                                                                    Import the file from the url with the following command:

                                                                                    trestle import -f https://raw.githubusercontent.com/usnistgov/oscal-content/master/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_catalog.json -o mycatalog\n

                                                                                    As a reminder, you could also have imported the file from a local directory on your file system, or an sftp:// address. But the file must first be imported to the trestle workspace in order for it to be directly manipulated by trestle as in this tutorial.

                                                                                    The import command will also check the validity of the file including the presence of any duplicate uuid's. If the file is manually created please be sure it conforms with the current OSCAL schema (OSCAL version 1.0.4) and has no defined uuid's that are duplicates. If there are any errors the Import will fail and the file must be corrected.

                                                                                    Your initial workspace will look like this
                                                                                    my_workspace\n \u2523 .trestle\n \u2503 \u2523 .keep\n \u2503 \u2517 config.ini\n \u2523 assessment-plans\n \u2503 \u2517 .keep\n \u2523 assessment-results\n \u2503 \u2517 .keep\n \u2523 catalogs\n \u2503 \u2523 mycatalog\n \u2503 \u2503 \u2517 catalog.json\n \u2503 \u2517 .keep\n \u2523 component-definitions\n \u2503 \u2517 .keep\n \u2523 dist\n \u2503 \u2523 assessment-plans\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 assessment-results\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 catalogs\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 component-definitions\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 plan-of-action-and-milestones\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 profiles\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2523 system-security-plans\n \u2503 \u2503 \u2517 .keep\n \u2503 \u2517 target-definitions\n \u2503 \u2503 \u2517 .keep\n \u2523 plan-of-action-and-milestones\n \u2503 \u2517 .keep\n \u2523 profiles\n \u2503 \u2517 .keep\n \u2523 system-security-plans\n \u2503 \u2517 .keep\n \u2517 target-definitions\n \u2503 \u2517 .keep\n

                                                                                    You will see that the directory now shows your catalog file in my_workspace/catalogs/mycatalog/catalog.json. Note that the .keep files are simply to make sure git does not remove the directories - and can be ignored. Also note that the json file itself is singular (catalog) while the directory above is plural (catalogs). This convention is used throughout trestle because a given model directory like catalogs may contain several individual models - each of which is singular. The imported catalog file size may be larger than the original due to a change in formatting, but the contents should be the same.

                                                                                    From here on in this tutorial we will just focus on the catalogs directory since the others are not directly involved.

                                                                                    You have now populated your trestle workspace with an OSCAL catalog that you can manipulate. Let's start.

                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#step-3-split-the-file-into-smaller-parts","title":"Step 3: Split the file into smaller parts","text":"

                                                                                    The OSCAL schema specifies that a catalog must contain metadata, groups, and back-matter - so this command will pull them out of the original file and place them in separate json files for additional manipulations.

                                                                                    To begin splitting the file, first cd to the directory where catalog.json has been placed.

                                                                                    cd catalogs/mycatalog\ntrestle split -f ./catalog.json -e 'catalog.metadata,catalog.groups,catalog.back-matter'\n

                                                                                    Here the -f refers to the filename of the json catalog file, and -e refers to the comma-separated list of elements you would like to split from the file. This list does not represent the full file contents of the source catalog.json file, so some contents will be left behind in a much smaller catalog.json file after the split. The elements that were split off will be placed in separate json files next to the new and smaller catalog.json file.

                                                                                    Your new catalogs directory with json files split out
                                                                                    catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                                                                    Note there still remains a catalog.json file, but it is much smaller since the bulk of its contents have been split off.

                                                                                    Any split step can be reversed by a corresponding merge operation. In this case we can go backwards with:

                                                                                    trestle merge -e 'catalog.metadata,catalog.groups,catalog.back-matter'\n

                                                                                    or simply

                                                                                    trestle merge -e 'catalog.*'\n

                                                                                    You can go back and forth splitting and merging, but for the next step please start with the above files split so that metadata.json can be further split.

                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#step-4-split-the-metadata-into-constituent-files","title":"Step 4: Split the metadata into constituent files","text":"
                                                                                    cd catalog\ntrestle split -f ./metadata.json -e 'metadata.roles,metadata.parties,metadata.responsible-parties'\n
                                                                                    The directory will now look like this, with metadata split into files
                                                                                    catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2523 parties.json\n \u2503 \u2503 \u2503 \u2523 responsible-parties.json\n \u2503 \u2503 \u2503 \u2517 roles.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                                                                    Again there remains a metadata.json file but it is smaller than the original.

                                                                                    And this step can be reversed with the following:

                                                                                    trestle merge -e 'metadata.roles,metadata.parties,metadata.responsible-parties'\n

                                                                                    or simply

                                                                                    trestle merge -e 'metadata.*'\n
                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#step-5-split-metadata-further-using-wildcards","title":"Step 5: Split metadata further using wildcards","text":"
                                                                                    cd metadata\ntrestle split -f ./roles.json -e 'roles.*'\ntrestle split -f ./responsible-parties.json -e 'responsible-parties.*'\n
                                                                                    The directory now looks like this, with new subdirectories containing multiple roles and responsible-parties
                                                                                    catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2523 responsible-parties\n \u2503 \u2503 \u2503 \u2503 \u2523 contact__responsible-party.json\n \u2503 \u2503 \u2503 \u2503 \u2517 creator__responsible-party.json\n \u2503 \u2503 \u2503 \u2523 roles\n \u2503 \u2503 \u2503 \u2503 \u2523 00000__role.json\n \u2503 \u2503 \u2503 \u2503 \u2517 00001__role.json\n \u2503 \u2503 \u2503 \u2517 parties.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2523 groups.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                                                                    Note that the presence of wildcards caused new directories to be created containing the full lists of roles and responsible parties. You can read the wildcard as split off all roles from roles.json.

                                                                                    This split can be reversed with

                                                                                    trestle merge -e 'roles.*,responsible-parties.*'\n
                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#step-6-split-groups-and-controls-with-two-wildcards","title":"Step 6: Split groups and controls with two wildcards","text":"

                                                                                    This single command will split off all controls in all groups. To do it you need to go back up into the catalog directory where the groups.json file is found:

                                                                                    cd ..\ntrestle split -f ./groups.json -e 'groups.*.controls.*'\n

                                                                                    Your directory is now very large with that one command!
                                                                                    catalogs\n \u2517 mycatalog\n \u2503 \u2523 catalog\n \u2503 \u2503 \u2523 groups\n \u2503 \u2503 \u2503 \u2523 00000__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00022__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00023__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00024__control.json\n \u2503 \u2503 \u2503 \u2523 00001__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00005__control.json\n \u2503 \u2503 \u2503 \u2523 00002__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00015__control.json\n \u2503 \u2503 \u2503 \u2523 00003__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00008__control.json\n \u2503 \u2503 \u2503 \u2523 00004__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00013__control.json\n \u2503 \u2503 \u2503 \u2523 00005__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00012__control.json\n \u2503 \u2503 \u2503 \u2523 00006__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00011__control.json\n \u2503 \u2503 \u2503 \u2523 00007__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00009__control.json\n \u2503 \u2503 \u2503 \u2523 00008__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00006__control.json\n \u2503 \u2503 \u2503 \u2523 00009__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00007__control.json\n \u2503 \u2503 \u2503 \u2523 00010__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00022__control.json\n \u2503 \u2503 \u2503 \u2523 00011__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00010__control.json\n \u2503 \u2503 \u2503 \u2523 00012__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00022__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00023__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00024__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00025__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00026__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00027__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00028__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00029__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00030__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00031__control.json\n \u2503 \u2503 \u2503 \u2523 00013__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00008__control.json\n \u2503 \u2503 \u2503 \u2523 00014__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00007__control.json\n \u2503 \u2503 \u2503 \u2523 00015__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00009__control.json\n \u2503 \u2503 \u2503 \u2523 00016__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00022__control.json\n \u2503 \u2503 \u2503 \u2523 00017__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00022__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00023__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00024__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00025__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00026__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00027__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00028__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00029__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00030__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00031__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00032__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00033__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00034__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00035__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00036__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00037__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00038__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00039__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00040__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00041__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00042__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00043__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00044__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00045__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00046__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00047__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00048__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00049__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00050__control.json\n \u2503 \u2503 \u2503 \u2523 00018__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00011__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00012__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00013__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00014__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00015__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00016__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00017__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00018__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00019__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00020__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00021__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00022__control.json\n \u2503 \u2503 \u2503 \u2523 00019__group\n \u2503 \u2503 \u2503 \u2503 \u2517 controls\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00000__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00001__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00002__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00003__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00004__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00005__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00006__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00007__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00008__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00009__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2523 00010__control.json\n \u2503 \u2503 \u2503 \u2503 \u2503 \u2517 00011__control.json\n \u2503 \u2503 \u2503 \u2523 00000__group.json\n \u2503 \u2503 \u2503 \u2523 00001__group.json\n \u2503 \u2503 \u2503 \u2523 00002__group.json\n \u2503 \u2503 \u2503 \u2523 00003__group.json\n \u2503 \u2503 \u2503 \u2523 00004__group.json\n \u2503 \u2503 \u2503 \u2523 00005__group.json\n \u2503 \u2503 \u2503 \u2523 00006__group.json\n \u2503 \u2503 \u2503 \u2523 00007__group.json\n \u2503 \u2503 \u2503 \u2523 00008__group.json\n \u2503 \u2503 \u2503 \u2523 00009__group.json\n \u2503 \u2503 \u2503 \u2523 00010__group.json\n \u2503 \u2503 \u2503 \u2523 00011__group.json\n \u2503 \u2503 \u2503 \u2523 00012__group.json\n \u2503 \u2503 \u2503 \u2523 00013__group.json\n \u2503 \u2503 \u2503 \u2523 00014__group.json\n \u2503 \u2503 \u2503 \u2523 00015__group.json\n \u2503 \u2503 \u2503 \u2523 00016__group.json\n \u2503 \u2503 \u2503 \u2523 00017__group.json\n \u2503 \u2503 \u2503 \u2523 00018__group.json\n \u2503 \u2503 \u2503 \u2517 00019__group.json\n \u2503 \u2503 \u2523 metadata\n \u2503 \u2503 \u2503 \u2523 responsible-parties\n \u2503 \u2503 \u2503 \u2503 \u2523 contact__responsible-party.json\n \u2503 \u2503 \u2503 \u2503 \u2517 creator__responsible-party.json\n \u2503 \u2503 \u2503 \u2523 roles\n \u2503 \u2503 \u2503 \u2503 \u2523 00000__role.json\n \u2503 \u2503 \u2503 \u2503 \u2517 00001__role.json\n \u2503 \u2503 \u2503 \u2517 parties.json\n \u2503 \u2503 \u2523 back-matter.json\n \u2503 \u2503 \u2517 metadata.json\n \u2503 \u2517 catalog.json\n

                                                                                    All 20 groups of controls have been split off, and each one has a corresponding directory with its full list of controls in it.

                                                                                    You can then reverse the split with

                                                                                    trestle merge -e 'groups.*'\n
                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#step-7-collapse-the-entire-directory-structure-back-into-a-single-catalogjson-file-possibly-after-modifying-individual-files","title":"Step 7: Collapse the entire directory structure back into a single catalog.json file - possibly after modifying individual files","text":"

                                                                                    You can collapse everything back to a single catalog.json file after first going up one directory to the mycatalog directory

                                                                                    cd ..\ntrestle merge -e 'catalog.*'\n

                                                                                    After all that splitting and merging you are back to this directory structure
                                                                                    catalogs\n \u2517 mycatalog\n \u2503 \u2517 catalog.json\n

                                                                                    "},{"location":"tutorials/trestle_sample_workflow/#conclusion","title":"Conclusion","text":"

                                                                                    This completes the tutorial on using trestle to split and merge an OSCAL catalog file. Not shown here are modifications of the individual files that would be done in an actual use case, but note that if any changes are made that violate the OSCAL schema, trestle will notice them and flag them in the merge. This way not only does trestle allow user-driven decomposition and aggregation of these large, complex files; it also does constant checks on the contents against the required schema to make sure no errors are introduced in the process.

                                                                                    "},{"location":"tutorials/continuous-compliance/continuous-compliance/","title":"Tutorial: What\u2019s your compliance posture?","text":""},{"location":"tutorials/continuous-compliance/continuous-compliance/#introduction","title":"Introduction","text":"

                                                                                    The cloud with its continuous integration and continuous deployment is the modern computing paradigm. There is a plethora of cloud environments: public, private, on-premise, hybrid-cloud, multi-cloud, etc. along with a corresponding contingent of vendors. The cloud offers great flexibility where you can choose just one or some combination optimal for each application. But, as demonstrated from time to time, the cloud can be a dangerous place. Hackers, bots, malware, and more are constant threats seeking to find and exploit weakness in your computing solution. To combat them there are strategies to avoid embarrassment and financial ruin from security breeches. Educating your workforce is of paramount importance. Moreover, employing a trust-but-verify strategy will go a long way toward deflecting trouble.

                                                                                    The time has come for continuous auditing, and giving stakeholders (such as account owners, application owners, system owners and compliance officers) a current picture of their compliance posture:

                                                                                    • Are password rules being followed?
                                                                                    • Are deployed applications using compromised encryption algorithms?
                                                                                    • Has a user gotten elevated privileges?
                                                                                    • Are unauthorized open source projects wrongfully part of your application stack?

                                                                                    Getting answers to these questions only quarterly or annually is leaving you exposed.

                                                                                    Moreover, assuring continuous compliance across multiple cloud vendors can complicate matters. If each has its own compliance regime, then one must become expert in each domain\u2019s compliance solution space, or else be wedded to a single or few providers. That is not an ideal prospect.

                                                                                    Common sense dictates that standardization would simplify matters. The National Institute of Standards and Technologies (NIST) is developing the Open Security Controls Assessment Language (OSCAL).

                                                                                    The compliance-trestle open source github project is an effort to employ OSCAL for compliance standardization and automation. Of great utility is the trestle oscal module that facilitates transformation of data to/from Python object representations in accordance with the OSCAL schemas.

                                                                                    "},{"location":"tutorials/continuous-compliance/continuous-compliance/#simple-continuous-compliance-architecture","title":"Simple Continuous Compliance Architecture","text":"

                                                                                    Cloud Services can often be configured to monitor (and sometimes enforce) policies. Examples include OpenShift Compliance Operator and Tanium. However, the compliance reporting \u201craw\u201d data produced is unique to each.

                                                                                    Two steps are needed to ascertain your compliance posture. Step 1 is to transform available compliance \u201craw\u201d data into standardized form (OSCAL). Step 2 is to examine the OSCAL data and assemble a compliance posture for the controls and components of interest. And trestle is the go-to solution.

                                                                                    "},{"location":"tutorials/continuous-compliance/continuous-compliance/#step-1-transformation","title":"Step 1 \u2013 Transformation","text":"

                                                                                    The bad news is that a transformer to OSCAL is needed for each Cloud Service type.

                                                                                    However, there is plenty of good news:

                                                                                    • a transformer for your Cloud Service type may already exist, such as: Tanium to OSCAL, OpenShift Compliance Operator to OSCAL
                                                                                    • once a transformer for a Cloud Service type has been written, it can be open-sourced/re-used
                                                                                    • writing a transformer is fairly easy: just a few lines of Python code using trestle as a foundation

                                                                                    In the case of Tanium, the OSCAL compliance data document is a System Assessment Results fragment with Findings and Observations, while in the case of OpenShift Compliance Operator there are Observations only.

                                                                                    Tutorials are available to show you: how to run a transformer, how to write a transformer.

                                                                                    "},{"location":"tutorials/continuous-compliance/continuous-compliance/#step-2-reporting","title":"Step 2 \u2013 Reporting","text":"

                                                                                    Coming soon is a trestle tool to assemble the OSCAL fragments documents together using OSCAL compliance configuration data (System Assessment Plan and System Security Plan) into a complete System Assessment Results.

                                                                                    "},{"location":"tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/","title":"Tutorial: Catalog, Profile, ComponentDefinition, and SSP Authoring","text":""},{"location":"tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/#introduction-and-background","title":"Introduction and background","text":"

                                                                                    In addition to core functionality for automated processing of OSCAL documents, Trestle has authoring tools that allow conversion of OSCAL documents to markdown for easy editing - and conversion back to OSCAL for validation and automation. A big part of compliance involves writing guidance prose associated with controls, along with the setting of parameters and properties for those controls. This cannot be completely automated because it requires human editing, along with human approvals of those edits. The purpose of the authoring tools is to allow selected edits of oscal documents guided by prompts for where content is required. This serves to streamline the edit/approval process whereby the author is presented with one markdown document per control, and it provides a view of the the key information needed during the editing process. This greatly simplifies the editing process compared to multiple authors working together on a single large JSON document.

                                                                                    The key modes of authoring are -generate and -assemble. During -generate a JSON document is converted to markdown format, allowing authors to add or edit prose and parameter values. After editing, the markdown can then be -assembled into the same or a new JSON document that captures the edit changes. In a normal authoring cycle, the markdown is generated for the first time from a given JSON file, and after that there is a continuous process of editing and reassembling to keep the JSON up to date with the markdown edits.

                                                                                    A third mode of authoring is -filter, where parts of a document are removed. This allows one large master document to be represented in simpler ways with, e.g. proprietary prose culled in form intended for consumption outside a company.

                                                                                    Integration with git and CI/CD

                                                                                    The command line interface in Trestle makes a powerful combination with git and CI/CD environments (Continuous Integration, Continuous Delivery or Deployment) when the trestle commands are performed via github actions or equivalent. This allows different classes of users based on 1) their access to the repository 2) the changes to documents they are allowed to commit, and 3) the changes they can make to actions that are triggered by a commit. As an example, a command line option may limit the type of content added to a profile, and if disallowed changes are detected during commit - the commit will be rejected. This, in combination with having all controls as individual markdown files organized by groups in directories, makes management and tracking of author edits robust and automatically controlled by the built-in features of the respository.

                                                                                    For an example of actions triggered by a commit, a change to a control in a catalog could generate a pull request that is approved by someone with appropriate authority, and when it is later merged it triggers notification downstream to authors of profiles that import that catalog.

                                                                                    The author commands

                                                                                    The author commands are:

                                                                                    1. catalog-generate converts a control Catalog to individual controls in markdown format for addition or editing of guidance prose and parameters, with parameters stored in a yaml header at the top of the markdown file. catalog-assemble then gathers the prose and parameters and updates the controls in the Catalog to make a new OSCAL Catalog.
                                                                                    2. profile-generate takes a given Profile and converts the controls represented by its resolved profile catalog to individual controls in markdown format, with sections corresponding to the content that the Profile adds to the Catalog, along with both the current values of parameters in the resolved profile catalog - and the values that are being modified by the given profile's SetParameters. The user may edit the content or add more, and profile-assemble then gathers the updated content and creates a new OSCAL Profile that includes those changes.
                                                                                    3. profile-resolve is special as an authoring tool because it does not involve markdown and instead it simply creates a JSON resolved profile catalog from a specified JSON profile in the trestle directory. There are options to specify whether or not parameters get replace in the control prose or not, along with any special brackets that might be desired to indicate the parameters embedded in the prose.
                                                                                    4. profile-inherit takes a given parent profile and filters its contents based on the inherited controls included in a given ssp to be include in the final profile.
                                                                                    5. component-generate takes a given ComponentDefinition file and represents all the controls in markdown in separate directories for each Component in the file. This allows editing of the prose on a per-component basis. component-assemble then assembles the markdown for all controls in all component directories into a new, or the same, ComponentDefinition file.
                                                                                    6. ssp-generate takes a given Profile and an optional list of component-definitions, and represents the individual controls as markdown files with sections that prompt for prose regarding the implementation response for items in the statement of the control, with separate response sections for each component. ssp-assemble then gathers the response sections and creates an OSCAL System Security Plan comprising the resolved profile catalog and the implementation responses for each component. The list of component-definitions is optional, but without them the SSP will only have one component: This System. Rules, parameters and status associated with the implemented requirements are stored in the SetParameters and Properties of the components in the component definitions and represented in the markdown, allowing changes to be made to the parameter values and status. These edits are then included in the assembled SSP. Note that the rules themselves may not be edited and strictly correspond to what is in the component definitions.
                                                                                    7. ssp-filter takes a given ssp and filters its contents based on the controls included in a provided profile, or in a list of components to be included in the final ssp.

                                                                                    In summary, the catalog tools allow conversion of a Catalog to markdown for editing - and back again to a Catalog. The profile tools similarly convert a Profile's resolved profile catalog to markdown and allow conversion to a new Profile with modified additions that get applied in resolving the profile catalog. component tools perform similarly for ComponentDefinitions. Finally, the ssp tools allow the addition of implementation prose to the markdown of a system security plan, which is then assembled into a JSON SSP on a by-component basis.

                                                                                    Note that the original ssp implementation in trestle created SSP's by adding prose directly to the SSP markdown on a per-component basis, and there was no connection with separate ComponentDefinition JSON files. This is now changed so that control responses can be added to the ComponentDefinition and then merged to create the SSP markdown. In addition, rules and status are captured in the component definition as properties that propogate via markdown into the assembled SSP. The OSCAL schema doesn't include a form of implementation status for components in the component definition, which is why trestle embeds the status value in the properties. Similarly, rules and rule parameter values are not currently part of the schema, so they are also embedded in properties.

                                                                                    Some details of the author commands

                                                                                    The markdown files for controls usually have a YAML header at the top containing metadata about the control. Sometimes that information is read-only and intended as additional information useful during markdown editing, but in other cases the content may be edited and incorporated as new values for the control after -assemble. In addition, most -generate commands allow specifying a separate YAML header file containing information either needed by the command, or intended to be incorporated into the header of each control markdown file. When generating markdown a YAML header may be optionally provided, and if so, the option --overwrite-header-values will cause the values in the provided YAML header to overwrite the value in the markdown file's header for any items that are common. Otherwise the provided YAML header will simply insert any values not already in the markdown header. By default, Trestle will preserve the history of the changes in generated markdowns, however --force-overwrite option can be used to overwrite markdowns with content from JSON. Note that this option will completely delete all existing markdowns (in the given output folder) without saving any changes. To save the changes, run assemble first. Similarly, when assembling to JSON, the --set-parameters option will cause any changes in the header to take effect and change values in the assembled JSON for the control. The changes can including setting parameter and property values. The --set-parameters option is available only for catalog-assemble and profile-assemble.

                                                                                    As described earlier, the authoring tools are designed to work well in a CI/CD environment where changes are made in a pipeline by people with different responsibilities and authority. In this setting, changes to documents can trigger changes downstream, e.g. the editing of a control would cause an update in the catalog, which could then flow down to an updated SSP. These changes can occur automatically via actions that restrict the potential changes to the generated documents. Examples are the --set-parameters option on the -assemble tools, and both --required-sections and allowed-sections for profile-assemble. If a document change triggers an assemble action, changes to parameters can only occur if the action has --set-parameters in the command. Similarly, profile-assemble will fail if the sections do not meet the requirements specified in the command options. Another feature of the -assemble tools is that they won't create a new OSCAL file if the output already exists and its content would not be changed. This prevents undesired triggering of downstream actions when there is no actual change in content.

                                                                                    There is a standalone demonstration of the SSP generation process with trestle in the Trestle SSP Demo that captures the entire process of SSP authoring: from creation of a component definition from CSV file to a final formatted system security plan in Word (.docx) format.

                                                                                    Background on underlying concepts

                                                                                    In order to understand the specific operations handled by these commands, it is helpful to clarify some of the underlying OSCAL structures and how they can be edited in markdown form. This tutorial should be viewed in the context of the extensive documentation provided by OSCAL.

                                                                                    First, a Catalog is a collection of Controls, and a Profile imports controls and allows modification and additions to the controls, but it does not create new controls. A Profile has one or more Imports that refer either to an actual Catalog, or another Profile that itself is importing from a Catalog or Profile. The profiles can import controls selectively from each source and make additions or modifications to properties of the controls. The final collection of selected and modified controls represents the profile's resolved profile catalog.

                                                                                    For clarity, here is a simple depicton of a catalog as a collection of controls:

                                                                                    Here is a profile pulling controls from a catalog to make a resolved profile catalog:

                                                                                    And here is a more complex situation where a single profile pulls controls from catalogs and profiles:

                                                                                    From the diagram it's clear that the profile is performing many tasks under the covers. This is shown in an expanded view of a profile:

                                                                                    It's important to note that each profile is importing a selection of controls from each source, then making its own suggested modifications to parameters and other content in those controls. They are suggested in the sense that downstream profiles may override those settings - with priority given to the later profiles in the pipeline. The changes made by upstream profiles may be accepted, or overridden by better choices for a given need. This way the catalogs themselves can remain relatively static, and individual use cases can effectively create a custom catalog based on the original controls plus modifications by other static profiles, and/or the user's custom profile. The authoring tools here provide ways to make those modifications, both to the catalog controls and to the profiles, and to enter the implementation responses that are needed in a System Security Plan.

                                                                                    The tools are designed to be used in a continuous generate-edit-assemble cycle, with previous edits retained in each cycle. Each new edit phase can add or modify the current content, allowing a new generate of an OSCAL json document capturing those edits.

                                                                                    NOTE: We use json format for specifying OSCAL files in this tutorial, but it is equally applicable to yaml format also.

                                                                                    "},{"location":"tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/#the-author-commands-for-markdown-generation-and-assembly-to-json","title":"The author commands for markdown generation and assembly (to JSON)","text":"trestle author catalog-generate and trestle author catalog-assemble

                                                                                    catalog-generate takes an existing json catalog and writes it out as markdown files for each control in a user-specified directory. That directory will contain subdirectories for each group in the catalog, and those directories may contain subdirectories for groups within groups. But controls containing controls are always split out into a series of controls in the same directory - and each control markdown file corresponds to a single control.

                                                                                    We now look at the contents of a typical control markdown file.

                                                                                    A Control may contain many parts, but only one of them is a Statement, which describes the function of the control. The statement itself is broken down into separate items, each of which may contain parameter id's in \"moustache\" ({{}}) brackets. Below is an example of a control as generated in markdown form by the catalog-generate command.

                                                                                    Control example
                                                                                    ---\nx-trestle-set-params:\n  ac-1_prm_1:\n    values:\n      - new value\n  ac-1_prm_2:\n    values:\n  ac-1_prm_3:\n    values:\n      - added param 3 value\n  ac-1_prm_4:\n    values:\n  ac-1_prm_5:\n    values:\n  ac-1_prm_6:\n    values:\n  ac-1_prm_7:\n    values:\nx-trestle-global:\n  sort-id: ac-01\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\n- \\[a.\\] Develop, document, and disseminate to {{ insert: param, ac-1_prm_1 }}:\n\n  - \\[1.\\]  {{ insert: param, ac-1_prm_2 }} access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an {{ insert: param, ac-1_prm_3 }} to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy {{ insert: param, ac-1_prm_4 }} and following {{ insert: param, ac-1_prm_5 }}; and\n  - \\[2.\\] Procedures {{ insert: param, ac-1_prm_6 }} and following {{ insert: param, ac-1_prm_7 }}.\n- \\[d\\] My added item\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. \n

                                                                                    The control markdown files rely on brackets around key items that are important in defining the control's properties and structure. \\[Access Control\\] at the top indicates the title of the group containing the control. The name of the control is already known from the name of the markdown file (ac-1.md) and the name of the group is already known from the name of the directory containing the group's controls (ac) - but the group title must be indicated in the control in a special manner, hence the brackets. The text following the group title is the title of the control itself. All controls in a group should have the same group title or a warning will be indicated in certain trestle operations.

                                                                                    In addition, each part label corresponds to the label used in the OSCAL structure for the control statement, and so must be maintained in a special manner - hence the need for brackets on \\[(a)\\].

                                                                                    The items in moustaches ({{}}) correspond to the original prose from the control description. The moustaches represent places to substitue parameter values, but no substitutions are ever made until the final SSP generation. The authoring process provides multiple ways to set and change the final parameter values, as described below.

                                                                                    catalog-generate is run with the command trestle author catalog-generate --name catalog_name --output markdown_dir, where catalog_name is the name of a catalog already loaded into the trestle workspace, and markdown_dir is the directory into which the markdown files for the controls will be written. A separate directory is created for each group in the catalog.

                                                                                    A user then may edit the control statement for the control and add or change the contents. In this case an added item, My added item is shown as item d. You can then assemble the edited controls into a new catalog with the command trestle author catalog-assemble --markdown markdown_dir --output new_catalog. This will load the updated control statements for each control into a new json or yaml catalog named new_catalog.

                                                                                    As with profile and ssp generation described below, a yaml header may be provided with the --yaml option that is inserted into the top of each control file. If a control file already exists, as is expected in a continuous cycle of generate-edit-assemble, then the provided header will be merged with the existing header in each control. If a given item in the header is already present in the control, by default the values in the markdown header will be given priority, though this can be overridden by the --overwrite-header-values option, which will give priority to any values coming from the provided yaml header. In all cases, values in the yaml header not already present in the markdown header will be inserted.

                                                                                    In the control markdown example above, the header contains some arbitrary values along with a special x-trestle-set-params section containing parameters for some of the parameters in the control. Any parameters for the control in the catalog will appear in the markdown header automatically during catalog-generate. These values may be changed and values for other parameters may be inserted into the markdown header for later use during catalog-assemble.

                                                                                    Parameters in the header are shown with a subset of their full OSCAL attributes in order to convey any values they may have along with descriptive text. This amounts to the parameter id, its label if present, any values if present, and any select if present. When a select is present the list of choices is provided along with the how-many option. Note that values is a list in OSCAL, but in many cases it is a list of only one item. As a result, for convenience the values: dictionary may either have one string value (on the same line with values:) or as an indented - list of multiple values underneath values:. Multiple examples are evident in the sample above, including ac-1_prm_3, which only has a label and no values.

                                                                                    Another important item in the header is the sort-id for the control. This specifies how the controls and their parameters are ordered in any aggregated list operation. If it is not specified for a control, the control's id is used for sorting.

                                                                                    As with the other -generate tools, the --force-overwrite option will cause the destination markdown directory to be erased prior to generating the new markdown, so that any prior edits to the markdown will be erased.

                                                                                    catalog-assemble is run with the command catalog-assemble --markdown my_md --output my_new_catalog. This will read the markdown for each control and create a new catalog based on any edits to the markdown. Note that you may optionally provide a --name option specifying an original json catalog into which the updated controls are inserted, and the resulting catalog can either replace the original one or output to a different json file. New controls may be added but existing controls may not be removed and new groups cannot be added when you are updating an existing catalog. The main benefit of updating an existing catalog is that the original metadata and other contents of the catalog json file will be retained. Note that you cannot create new controls that contain controls, but if an original json catalog contains controls with child controls, you can edit and update all of them as individual markdown files. You have the option to specify a new --version for the catalog, and an option to regenerate the uuid's in the catalog. Finally, you have the option to use the parameters in the markdown header to update the values in the control. Any parameters and their values present will be added to the control, and any not present will be removed. The parameters themselves are still present but their values are removed.

                                                                                    In a typical generate-edit-assemble cycle, the cycle would start with an original json file containing source content and metadata and use that to generate an initial markdown directory of controls. After editing the controls they would be assembled into into a new json file with a different name. But once that new file exists, it can be used as the source for the next generation and the original source document is no longer needed or referred to. For the catalog- editing cycle it would go as:

                                                                                    trestle author catalog-generate --name orig_catalog --output md_catalog\n[user edits the markdown files]\ntrestle author catalog-assemble --name orig_catalog --markdown md_catalog --output assembled_catalog\n[user makes additional markdown edits]\ntrestle author catalog-assemble --markdown md_catalog --output assembled_catalog\n

                                                                                    The key point here is that the first -assemble needs to use the original catalog for its metadata, backmatter and other items not captured in the markdown controls. But once the output catalog has been created, by default it will be used as the \"original\" or \"parent\" catalog into which changes will be incorporated, unless a different source catalog is specified via --name.

                                                                                    Note that catalog-assemble can instantiate a catalog anew from a manually created directory of markdown controls in directories corresponding to groups, but the metadata in the assembled json catalog will contain many REPLACE_ME items that would need to be manually edited in the json file itself. The trestle split and merge tools may help in that case. Once the changes have been made they will be retained if a new catalog-assemble happens with that same output file as the target.

                                                                                    Special Note about assemble: In order to avoid triggering actions when a new file is created that has no actual changes in it, catalog-assemble and the other -assemble tools below will check to see if the output file already exists, and if so it will be examined for changes relative to the newly assembled one. If there are no changes the file will not be written out. Note that the check happens before any possible --regeneration of uuid's, and after any possible --version change. This avoids the creation of a new file and new uuid's if there is no change to the version or other file contents relative to the existing output file, but if the specified --version is different from the one in the existing output file, or there is any other difference in the model, a new file will be written out.

                                                                                    trestle author profile-generate and trestle author profile-assemble

                                                                                    The background text above conveys how a profile pulls controls from catalogs and makes modifications to them, and the trestle profile tools let you change the way those modifications are made. In addition to selecting controls and setting parameters, a profile may add new parts to a control that provide additional guidance specific to a certain use case. profile-generate is run with the command, trestle author profile-generate --name profile_name --output markdown_dir. It will load the specified profile name from the trestle workspace (it must have been imported into the trestle workspace prior) and create its corresponding resolved profile catalog - but without applying any of its Adds of additonal guidance content or SetParameters. It will make all other modifications, but the Adds and SetParameters are kept separate, as shown below:

                                                                                    Example of control markdown after `profile-generate`
                                                                                    ---\nx-trestle-set-params:\n  # You may set values for parameters in the assembled Profile by adding\n  #\n  # profile-values:\n  #   - value 1\n  #   - value 2\n  #\n  # in the section under a parameter name\n  # The values list refers to the values in the catalog, and the profile-values represent values\n  # in SetParameters of the Profile.\n  #\n  ac-1_prm_1:\n    label: label from edit\n    profile-values:\n      - all personnel\n    values:\n      - Param_1_value_in_catalog\n    display-name: Pretty ac-1 prm 1\n  ac-1_prm_2:\n    profile-values:\n      - Organization-level\n      - System-level\n    values:\n    display-name: Pretty ac-1 prm 2\n  ac-1_prm_3:\n    profile-values:\n      - new value\n    values:\n  ac-1_prm_4:\n    profile-values:\n    values:\n  ac-1_prm_5:\n    profile-values:\n      - all meetings\n    values:\n  ac-1_prm_6:\n    profile-values:\n      - monthly\n    values:\n  ac-1_prm_7:\n    values:\nx-trestle-global:\n  profile:\n    title: Trestle test profile\n  sort-id: ac-01\nx-trestle-sections:\n  guidance: Guidance\n  implgdn: Implementation Guidance\n  expevid: Expected Evidence\n  my_guidance: My Guidance\n  a_guidance: A Guidance\n  b_guidance: B Guidance\n  NeededExtra: Needed Extra\n  a_subpart: A Subpart\n  a_subsubpart: A Subsubpart\n  b_subpart: B Subpart\n  a_by_id_subpart: a by_id subpart\nx-trestle-add-props:\n  # Add or modify control properties here\n  # Properties may be at the control or part level\n  # Add control level properties like this:\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #\n  # Add properties to a statement part like this, where \"b.\" is the label of the target statement part\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #     smt-part: b.\n  #\n  - name: prop_with_ns\n    value: prop with ns\n    ns: https://my_new_namespace\n  - name: prop_with_no_ns\n    value: prop with no ns\n    ns: https://my_added_namespace\n---\n\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\n- \\[a.\\] Develop, document, and disseminate to {{ insert: param, ac-1_prm_1 }}:\n\n  - \\[1.\\]  {{ insert: param, ac-1_prm_2 }} access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an {{ insert: param, ac-1_prm_3 }} to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy {{ insert: param, ac-1_prm_4 }} and following {{ insert: param, ac-1_prm_5 }}; and\n  - \\[2.\\] Procedures {{ insert: param, ac-1_prm_6 }} and following {{ insert: param, ac-1_prm_7 }}.\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. Policies and procedures contribute to security and privacy assurance. Therefore, it is important that security and privacy programs collaborate on the development of access control policy and procedures. Security and privacy program policies and procedures at the organization level are preferable, in general, and may obviate the need for mission- or system-specific policies and procedures. The policy can be included as part of the general security and privacy policy or be represented by multiple policies reflecting the complex nature of organizations. Procedures can be established for security and privacy programs, for mission or business processes, and for systems, if needed. Procedures describe how the policies or controls are implemented and can be directed at the individual or role that is the object of the procedure. Procedures can be documented in system security and privacy plans or in one or more separate documents. Events that may precipitate an update to access control policy and procedures include assessment or audit findings, security incidents or breaches, or changes in laws, executive orders, directives, regulations, policies, standards, and guidelines. Simply restating controls does not constitute an organizational policy or procedure.\n\n# Editable Content\n\n<!-- Make additions and edits below -->\n<!-- The above represents the contents of the control as received by the profile, prior to additions. -->\n<!-- If the profile makes additions to the control, they will appear below. -->\n<!-- The above markdown may not be edited but you may edit the content below, and/or introduce new additions to be made by the profile. -->\n<!-- If there is a yaml header at the top, parameter values may be edited. Use --set-parameters to incorporate the changes during assembly. -->\n<!-- The content here will then replace what is in the profile for this control, after running profile-assemble. -->\n<!-- The added parts in the profile for this control are below.  You may edit them and/or add new ones. -->\n<!-- Each addition must have a heading either of the form ## Control my_addition_name -->\n<!-- or ## Part a. (where the a. refers to one of the control statement labels.) -->\n<!-- \"## Control\" parts are new parts added after the statement part. -->\n<!-- \"## Part\" parts are new subparts added into the existing top-level statement part with that label. -->\n<!-- Subparts may be added with nested hash levels of the form ### My Subpart Name -->\n<!-- underneath the parent ## Control or ## Part being added -->\n<!-- See https://oscal-compass.github.io/compliance-trestle/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring for guidance. -->\n\n## Control Implementation Guidance\n\nDo it carefully.\n\n## Control Expected Evidence\n\nDetailed logs.\n\n## Control Needed Extra\n\nAdd prose here for required Section: Needed Extra\n\n## Control A Guidance\n\nControl level guidance\n\n### A Subpart\n\nA subpart prose\n\n#### A Subsubpart\n\nA subsubpart prose\n\n### B Subpart\n\nB subpart prose\n\n## Part a.\n\n### Subpart of top level Part a. of the control\n\nProse added as a sub-part to Part a. of the control\n

                                                                                    In the above markdown example, the fixed, uneditable parts of the control are output first (after the header, which can be edited), followed by a separate section marked, Editable Content. And below the editable content are the individual Adds that the profile makes, with each one marked by a header of the form, ## Control guidance_name or ## Part statement_part_label followed by named subparts. You may edit the editable content and you may add new Control guidance headers and statement sub-parts with your own new content. (Please refer to Markdown Specifications for Editable Content section below to learn more on which headers are valid in Trestle.) Then the command, trestle author profile-assemble --name original_profile --markdown markdown_dir --output new_profile will create a new OSCAL profile based on the original profile (specified) and the editable content in each control.

                                                                                    It's important to distinguish ## Control My New Guidance from ## Part a.. Parts added with ## Control will be new parts in the control added after the control statement, along with any subparts indicated by lower hash levels in that section. In contrast, parts added with e.g. ## Part c. will be added by-id to the top level part in the control statement with label c.. Thus \"My New Guidance\" is the title the user is assigning to a completely new part, while c. refers to a label corresponding the the desired control statement part.

                                                                                    When new part names are created in the markdown file the title is captured along with its capitalization and spaces, but the corresponding part name will be converted to snake case by default. However, the user may indicate a specific mapping of the long title of the part to its actual part name by providing an entry in the sections provided during profile-assemble. For example, in the above, the Needed Extra part would be assigned the name needed_extra but if you had a section entry such as n_ex:Needed Extra the name n_ex would be assigned in the assembled json profile, so that if you used that same section entry trestle would know to replace the n_ex part with Needed Extra in any generated markdown.

                                                                                    In a cyclic operation of profile generate-edit-assemble you would simply be re-writing from and to the same json profile, in which case the --name and --output are the same file. For this reason the default value for --name is the given output file name specified by --output and you can just use trestle author profile-assemble --markdown profile_md --output my_profile. This will assemble the markdown profile contents in directory profile_md into a json profile named my_profile but it will first use the existing my_profile json file as the parent profile and incorporate changes (due to user edits) in the markdown version of the profile. Unlike catalog-assemble there must always be a parent json profile to reference during assemble, but like catalog-assemble an explicit value for --name is only needed if the parent file is different from the assembled output file.

                                                                                    It's important to note that these operations only apply to the Adds and SetParameters in the profile itself - and nothing upstream of the profile is affected. Nor is anything else in the original profile lost or altered. In the example above, the section, ## Control Implementation Guidance was added by editing the generated control - and after profile-assemble it ended up as new guidance in the assembled profile.

                                                                                    As in the other commands, profile-generate allows specification of a yaml header with --yaml-header, support of the --overwrite-header-values flag and --force-overwrite. Also, during assembly with profile-assemble the --set-parameters flag will set parameters in the profile for the control based on the header in the control markdown file. But unlike with catalog-assemble, only those parameter values marked profile-values will be part of the assembled profile's SetParams when you assemble with the --set-parameters flag. For each parameter, the \"incoming\" values for the parameters prior to any changes made by the profile are listed as values: and any pending changes made by the profile are listed as profile-values:. If you don't use the --set-parameters flag then all the original SetParameters in the profile will be retained in the new, assembled profile. But if you do set that flag, then only the header parameters with profile-values: will be added as SetParameters. This lets you see all the incoming values for parameters along with any changes made by the current profile, and you can modify, add, or remove parameter settings as desired in the new profile.

                                                                                    The x-trestle-add-props key of the yaml header allows addition of properties to the SetParameters of the profile, comprising name, value, and optionally a namespace ns value. The properties may be added at the control level, or attached to a top level statment part by adding a value, smt-part with value a., b. or any other label for one of the top level statement parts.

                                                                                    For convenience, the x-trestle-global key of the yaml header contains the profile-title of the profile used to generate the markdown.

                                                                                    Keep in mind that the header in the profile- tools corresponds to the SetParameters in the profile - and not simply the Parameters in the control. For convenience the current incoming values of the control parameters, as set by any upstream profiles, are shown as values - but anything else associated with a parameter, such as profile-values, label, choice will be added to the profile's SetParameters during profile-assemble (if you use the --set-parameters flag.) So entries should be set there only if you want the profile to enforce those entries as SetParameters.

                                                                                    As with catalog-assemble described above, a new file is written out only if there are changes to the model relative to an existing output file, and during generate, --force-overwrite will first erase any existing markdown so that fresh markdown is created.

                                                                                    Use of Sections in profile-generate and profile-assemble

                                                                                    The addition of guidance sections in the profile tools requires special handling because the corresponding parts have both a name and a title, where the name is a short form used as an id in the json schema, while the title is the readable form intended for final presentation. An example is ImplGuidance vs. Implementation Guidance. The trestle authoring tools strive to make the markdown as readable as possible, therefore the headings for sections use the title - which means somehow there is a need for a mapping from the short name to the long title for each section. This mapping is provided in several ways: During profile-generate you may provide a --sections \"ImplGuidance:Implementation Guidance,ExpEvidence:Expected Evidence\" option that would provide title values for ImplGuidance and ExpEvidence. This dictionary mapping is then inserted into the yaml header of each control's markdown. You may also add this mapping directly to a yaml file that is passed in during profile-generate, which is preferable if the list of sections is long. The sections should be entered in the yaml header in a section titled, x-trestle-sections.

                                                                                    There is also a --required-sections option during both profile-generate and profile-assemble. This option expects a list of sections as comma-separated short names, e.g. --required-sections \"ImplGuidance,ExpEvidence\". During profile-generate any required sections will have in the markdown a prompt created for guidance prose to be entered. And during profile-assemble if required sections are specified, those sections must have prose filled in or it will fail with error.

                                                                                    Finally, profile-assemble also has an --allowed-sections option that restricts any added guidance to only those allowed sections - and if disallowed sections are present it will fail with error. If --allowed-sections is not specified then any sections found in the markdown will be added to the assembled profile.

                                                                                    Note that these section options are all optional and there isn't a need to provide this form of restriction and enforcement. But in order to have such sections read properly and mapped to the intended part names, a mapping must be provided in one of the ways described above. And for certain workflows, if the allowed and required sections are specified by a command that is run as an action outside the user's control, it allows restriction of what changes can or must be made to a profile in terms of added guidance.

                                                                                    (Note that the single quotes are required on Unix-like systems, but on Windows they are only needed if the contained string includes spaces, in which case double quotes should be used.)

                                                                                    Markdown Specifications for Editable Content.

                                                                                    For the ease of editing markdown in Github, Trestle's markdown parser follows Github Flavoured Markdown (GFM) specifications and therefore only certain Control headers will be parsed and added to the control.

                                                                                    A valid control header in Trestle is the header that is correctly displayed as such when reading or previewing the edited markdown on Github website.

                                                                                    In GFM, headers are considered to be any line of text that has any number of # symbols at the beginning. For example those are all valid headers and will be treated as such by Github:

                                                                                    # Valid header\n## Valid header \n##### Valid header\n# Valid <ins> header </ins> \n# Valid header <!-- some comment here -->\n

                                                                                    The headers above are valid Control headers and will be added to the control. However, there are multiple exceptions where the header will not be displayed. The header will not be displayed correctly if it is:

                                                                                    1. Written in the HTML comments or tags <ins> # not a header </ins> as well as multi-line comments:
                                                                                      <!--\n# not a header\n-->\n
                                                                                      or multi-line HTML blocks:
                                                                                      <dl> # not a header\n# not a header\n  <dt># not a header</dt>\n</dl>\n
                                                                                    2. Written in the single-line # not a header and multi-line code blocks:
                                                                                      # not a header \n
                                                                                    3. Written in the links [# not a header](url)
                                                                                    4. Trestle will also not support headers inside the blockquotes > # not a header

                                                                                    In all cases above Trestle markdown parser will skip such headers and it will be not added to the control.

                                                                                    trestle author profile-resolve

                                                                                    The trestle author profile-resolve command is different from the generate/assemble commands because it doesn't involve markdown and instead it takes an input profile and creates the corresponding resolved profile catalog in JSON format. In addition, it has several options for how parameters are represented in prose of the controls, and whether or not those values are substituted.

                                                                                    As an example, the prose in the statement for control AC-1 is:

                                                                                    Develops, documents, and disseminates to {{ insert: param, ac-1_prm_1 }}:

                                                                                    The parameter ac-1_prm_1 has a label: organization-defined personnel or roles and it may or may not have a value assigned by the profile being resolved. Suppose it has been assigned the value, my prm 1 value. In that case we can either leave the prose as-is (with the parameter in \"moustache\" form) in the resolved catalog, or we can substitute the value, or we can substitute the descriptive label. trestle supports all these options, along with an optional prefix to specify whether a value has been assigned or not - typically using the name of the organization responsible.

                                                                                    The --show-value -sv option will cause the value for the parameter to be substituted in the prose if it is available - otherwise the list of selection options if it has any, or simply the label prose if it has no options.

                                                                                    The --value-assigned-prefix -vap option adds a prefix to the value if the value is being assigned by the profile, and the --value-not-assigned-prefix -vnap will assign a prefix to parameters that do not have values assigned, along with the descriptive parameter label.

                                                                                    Finally, the --bracket-format -bf option specifies how the parameter representation will be wrapped in braces. The specification is done by placing characters around a single . symbol representing the parameter string, e.g. [.] will place square brackets around the parameter.

                                                                                    Note that these options that specify how the parameter is represented all require --show-value to be True, otherwise the raw prose with the moustache is produced.

                                                                                    As an example, if we use options

                                                                                    trestle author profile-resolve -n my_profile -o my_resolved_catalog -sv -bf [.] -vap \"ACME Assignment:\" -vnap \"Assignment:\"

                                                                                    the above prose would become:

                                                                                    Develops, documents, and disseminates to [ACME Assignment: my prm 1 value]:

                                                                                    (Note that you need appropriate use of quotation marks in the command for any strings that include spaces or special characters.)

                                                                                    And if the parameter did not have a value assigned the result would be:

                                                                                    Develops, documents, and disseminates to [Assignment: organization-defined personell or roles]:

                                                                                    Finally, if the parameter already had a value specified in the catalog, the value would be shown by itself in braces:

                                                                                    Develops, documents, and disseminates to [value in catalog]:

                                                                                    Similar substitution happens when a parameter has choices that themselves reference a parameter, such as:

                                                                                    \"id\": \"ac-4.4_prm_1\",\n\"select\": {\n  \"how-many\": \"one-or-more\",\n  \"choice\": [\n    \"decrypting the information\",\n    \"blocking the flow of the encrypted information\",\n    \"terminating communications sessions attempting to pass encrypted information\",\n    \" {{ insert: param, ac-4.4_prm_2 }} \"\n  ]\n

                                                                                    If the statement prose for AC-4.4 is:

                                                                                    The information system prevents encrypted information from bypassing content-checking mechanisms by {{ insert: param, ac-4.4_prm_1 }}.

                                                                                    and if a value pulling the plug has been assigned to ac-4.4_prm_2, the prose will be:

                                                                                    The information system prevents encrypted information from bypassing content-checking mechanisms by [Selection (one or more): decrypting the information, blocking the flow of the encrypted information, terminating the communications sessions attempting to pass encrypted information, [ACME Assignment: pulling the plug]].

                                                                                    There is a separate option from --show-values that will instead show only the descriptive labels for the parameters - again with an optional prefix. The options are --show-labels -sl and --label-prefix -lp. Note that there is no need for \"assigned\" or \"not assigned\" because no values are being shown - just the labels.

                                                                                    If we resolve the profile with options --show-labels --label-prefix \"Label:\" --bracket-format [.] the resulting prose from earlier would be:

                                                                                    Develops, documents, and disseminates to [Label: organization-defined personnel or roles]:

                                                                                    and any value present for the parameter would be ignored.

                                                                                    Similar options apply to the jinja authoring commands.

                                                                                    trestle author profile-inherit

                                                                                    The trestle author profile-inherit command is different from the generate/assemble commands because it doesn't involve markdown and instead it takes an parent profile and ssp and creates child profile in JSON format.

                                                                                    When utilizing a process with leveraged authorizations, use the command trestle author profile-inherit to create a profile with initial content using a parent profile and SSP with inheritable controls. The provided and responsibility statements for all by-component fields, as well as the implementation status, will be used to evaluate the leveraged SSP. To be filtered from the output profile (i.e. controls delta profile), all components must have exported provided statements, no exported responsibility statements, and an implementation status of implemented.

                                                                                    The filter command is invoked as:

                                                                                    trestle author profile-inherit --profile my_parent --ssp my_leveraged_ssp --output controls_delta_profile

                                                                                    Both the parent profile and the SSP must be present in the trestle workspace. This command produces a new workspace profile that imports the parent profile and filters the inherited controls from the SSP using the exclude-controls and include-controls fields in the profile import.

                                                                                    Example imports generated from profile-inherit
                                                                                      \"imports\": [\n{\n\"href\": \"trestle://profiles/controls_delta/profile.json\",\n\"include-controls\": [\n{\n\"with-ids\": [\n\"ac-2\"\n]\n}\n],\n\"exclude-controls\": [\n{\n\"with-ids\": [\n\"ac-1\"\n]\n}\n]\n}\n]\n
                                                                                    trestle author component-generate and component-assemble

                                                                                    The trestle author component-generate command takes a JSON ComponentDefinition file and creates markdown for its controls in separate directories for each of the DefinedComponents in the file. This allows specifying the implementation response and status for each component separately in separate markdown files for a control. In addition, the markdown captures Rules in the control that specify descriptions and parameter values that apply to the expected responses.

                                                                                    The command has few options compared to other author commands and only requires specifying --name and --output for the ComponentDefinition and output markdown directory, respectively.

                                                                                    Here is an example of the generated markdown for the component OSCO in the ComponentDefinition file. Note that this file will be under the subdirectory OSCO/source_name of the specified output directory - and any other DefinedComponents will have corresponding subdirectories level with the OSCO one. Here source_name refers to the name of the profile or catalog in the ComponentDefinition that is the source for this control. The control markdown files are written into directories split by both component name and source name. If the source refers to a general uri and not a named profile or catalog in the trestle directory, then names such as source_001 and source_002 are assigned. The actual source title can be found in the yaml header of any of the control markdown files.

                                                                                    Example of control markdown after component-generate
                                                                                    ---\nx-trestle-comp-def-rules:\n  comp_aa:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in aa\n    - name: comp_rule_aa_1\n      description: comp rule aa 1\nx-trestle-rules-params:\n  comp_aa:\n    - name: shared_param_1\n      description: shared param 1 in aa\n      options: '[\"shared_param_1_aa_opt_1\", \"shared_param_1_aa_opt_2\"]'\n      rule-id: top_shared_rule_1\nx-trestle-comp-def-rules-param-vals:\n  # You may set new values for rule parameters by adding\n  #\n  # component-values:\n  #   - value 1\n  #   - value 2\n  #\n  # below a section of values:\n  # The values list refers to the values as set by the components, and the component-values are the new values\n  # to be placed in SetParameters of the component definition.\n  #\n  comp_aa:\n    - name: shared_param_1\n      values:\n        - shared_param_1_aa_opt_1\nx-trestle-param-values:\n  ac-1_prm_1:\n    - prof_aa val 1\n  ac-1_prm_2:\n  ac-1_prm_3:\n  ac-1_prm_4:\n  ac-1_prm_5:\n  ac-1_prm_6:\n  ac-1_prm_7:\nx-trestle-global:\n  profile:\n    title: comp prof aa\n    href: trestle://profiles/comp_prof_aa/profile.json\n  sort-id: ac-01\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\nThe organization:\n\n- \\[a.\\] Develop, document, and disseminate to prof_aa val 1:\n\n  - \\[1.\\] Organization-level; Mission/business process-level; System-level access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an organization-defined official to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy organization-defined frequency and following organization-defined events; and\n  - \\[2.\\] Procedures organization-defined frequency and following organization-defined events.\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. Policies and procedures contribute to security and privacy assurance. Therefore, it is important that security and privacy programs collaborate on the development of access control policy and procedures. Security and privacy program policies and procedures at the organization level are preferable, in general, and may obviate the need for mission- or system-specific policies and procedures. The policy can be included as part of the general security and privacy policy or be represented by multiple policies reflecting the complex nature of organizations. Procedures can be established for security and privacy programs, for mission or business processes, and for systems, if needed. Procedures describe how the policies or controls are implemented and can be directed at the individual or role that is the object of the procedure. Procedures can be documented in system security and privacy plans or in one or more separate documents. Events that may precipitate an update to access control policy and procedures include assessment or audit findings, security incidents or breaches, or changes in laws, executive orders, directives, regulations, policies, standards, and guidelines. Simply restating controls does not constitute an organizational policy or procedure.\n\n______________________________________________________________________\n\n## What is the solution and how is it implemented?\n\n<!-- For implementation status enter one of: implemented, partial, planned, alternative, not-applicable -->\n\n<!-- Note that the list of rules under ### Rules: is read-only and changes will not be captured after assembly to JSON -->\n\nimp req prose for ac-1 from comp aa\n\n### Rules:\n\n- top_shared_rule_1\n\n### Implementation Status: implemented\n\n______________________________________________________________________\n\n## Implementation for part a.\n\nstatement prose for part a. from comp aa\n\n### Rules:\n\n- comp_rule_aa_1\n\n### Implementation Status: partial\n\n______________________________________________________________________\n

                                                                                    There is no direct way to specify rules in the ComponentDefinition, so they are specified via properties as shown here:

                                                                                    Representation of rules in the props of a ComponentDefinition
                                                                                    [\n{\n\"name\": \"Rule_Id\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp_rule_aa_1\",\n\"class\": \"Rule_Id\",\n\"remarks\": \"rule_2\"\n},\n{\n\"name\": \"Rule_Description\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp rule aa 1\",\n\"remarks\": \"rule_2\"\n},\n{\n\"name\": \"Rule_Id\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp_rule_aa_2\",\n\"class\": \"Rule_Id\",\n\"remarks\": \"rule_3\"\n},\n{\n\"name\": \"Rule_Description\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"comp rule aa 2\",\n\"class\": \"Rule_Description\",\n\"remarks\": \"rule_3\"\n},\n{\n\"name\": \"Parameter_Id\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"shared_param_1\",\n\"class\": \"Parameter_Id\",\n\"remarks\": \"rule_1\"\n},\n{\n\"name\": \"Parameter_Description\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"shared param 1 in aa\",\n\"class\": \"Parameter_Description\",\n\"remarks\": \"rule_1\"\n},\n{\n\"name\": \"Parameter_Value_Alternatives\",\n\"ns\": \"http://comp_ns\",\n\"value\": \"[\\\"shared_param_1_aa_opt_1\\\", \\\"shared_param_1_aa_opt_2\\\"]\",\n\"class\": \"Parameter_Value_Alternatives\",\n\"remarks\": \"rule_1\"\n}\n],\n\"set-parameters\": [\n{\n\"param-id\": \"shared_param_1\",\n\"values\": [\n\"shared_param_1_aa_opt_1\"\n],\n\"remarks\": \"set shared param aa 1\"\n}\n]\n

                                                                                    In this scheme the rules have a Rule_Id (e.g. comp_rule_aa_1 in this example) and an associated tag (rule_2) in the remarks section that binds the name to the description: Rule_Description=comp rule aa 1. In addition, rules may be associated with parameters specified here with Parameter_id=shared_param_1, Parameter_Description=shared param 1 in aa, and Parameter_Value_Alternatives=[\\\"shared_param_1_aa_opt_1\\\", \\\"shared_param_1_aa_opt_2\\\"]. Parameter_Value_Alternatives corresponds to possible Choices for the parameter value.

                                                                                    Also shown in this JSON excerpt is a normal set-parameter used to set the value of a parameter associated with a rule id. Thus the setting of the parameter follows the normal OSCAL schema for setting a parameter value, while the specification of the parameter and its options is specified via linked properties.

                                                                                    The markdown header lists all the rules that apply to this control, along with their descriptions, and for each implementation response, the rules that apply to it are shown. The association of an ImplementedRequirement with a rule is again done with properties as shown here:

                                                                                    Linking of ImplementedRequirement to a rule
                                                                                    {\n\"implemented-requirements\": [\n{\n\"uuid\": \"ca5ea4c5-ba51-4b1d-932a-5606891b7500\",\n\"control-id\": \"ac-1\",\n\"description\": \"imp req prose for ac-1 from comp aa\",\n\"props\": [\n{\n\"name\": \"Rule_Id\",\n\"value\": \"top_shared_rule_1\"\n},\n{\n\"name\": \"implementation-status\",\n\"value\": \"implemented\"\n}\n]\n}\n]\n}\n

                                                                                    The values for rule parameters are specified using the normal SetParameter mechanism in the ControlImplementation, but it's important to note that there are two different types of SetParameter: Those that apply to the normal parameters of the control, and those that apply strictly to the rules.

                                                                                    Note that markdown for a control is only created if there are rules associated with the control, and within the markdown the only parts written out that prompt for responses are parts that have rules assigned. Thus the output markdown directory may be highly pruned of both controls and groups of controls if only some controls have rules associated.

                                                                                    In addition, the rules should be regarded as read-only from the editing perspective, and you cannot change the rules associated with a control or its parts. But you may edit the rule parameter values as described in the comments of the markdown file under x-trestle-comp-def-rules-param-vals. You may also edit the prose and implementation status associated with a statement part at the bottom of the markdown file.

                                                                                    trestle author component-assemble

                                                                                    The component-assemble command will assemble the markdown into a ComponentDefinition file containing all the DefinedComponents in the markdown, and as usual it can either overwrite the original JSON file or create a new one. Edits made to the prose, status and rule parameter values in the markdown and header will be captured in the assembled file, but the list of rules attached with each ImplementedRequirement is readonly and new rule associations cannot be made via markdown.

                                                                                    trestle author ssp-generate and trestle author ssp-assemble

                                                                                    The ssp-generate command creates markdown for an SSP (System Security Plan) from a profile, optional component definitions, and optional yaml header file. ssp-assemble (described below) can then assemble the markdown files into a single json SSP file. The profile contains a list of imports that are either a direct reference to a catalog, or an indirect reference via a profile. There may be multiple imports of either type, and referenced profiles may themselves import either catalogs or profiles. Each profile involved may specify the controls that should be imported, along with any modifications to those controls. This command internally creates a resolved profile catalog and generates a directory containing a set of markdown files, one for each control in the resolved catalog. Each markdown file has the optional yaml header embedded at the start of the file.

                                                                                    The component definitions specify the components of the SSP, along with metadata associated with rules and status for the implemented requirements. The rules, rule parameters, and status values are encoded by properties within the components as described above for component-generate.

                                                                                    Example usage for creation of the markdown:

                                                                                    trestle author ssp-generate --profile my_prof --compdefs \"compdef_a,compdef_b\" --yaml /my_yaml_dir/header.yaml --output my_ssp

                                                                                    In this example the profile and component definitions have previously been imported into the trestle directory. The profile itself must be in the trestle directory, but the imported catalogs and profiles may be URI's with href's as described below.

                                                                                    The generated markdown output will be placed in the trestle subdirectory my_ssp with a subdirectory for each control group.

                                                                                    If the imported catalogs or profiles are not at the URI pointed to by the Import href of the profile then the href should be changed using the trestle href command.

                                                                                    Similar to catalog-generate, the --yaml and --overwrite-header-values flag may be specified to let the input yaml header overwrite values already specified in the header of the control markdown file. Also, the --force-overwrite option can be used to overwrite markdowns with content from JSON.

                                                                                    The resulting files look like this:

                                                                                    Example of control markdown after ssp-generate
                                                                                    ---\nx-trestle-comp-def-rules:\n  comp_aa:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in aa\n    - name: comp_rule_aa_1\n      description: comp rule aa 1\n  comp_ab:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in ab\n    - name: comp_rule_ab_1\n      description: comp rule ab 1\n  comp_ba:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in ba\n  comp_bb:\n    - name: top_shared_rule_1\n      description: top shared rule 1 in bb\nx-trestle-rules-params:\n  comp_aa:\n    - name: shared_param_1\n      description: shared param 1 in aa\n      options: '[\"shared_param_1_aa_opt_1\", \"shared_param_1_aa_opt_2\"]'\n      rule-id: top_shared_rule_1\n  comp_ab:\n    - name: shared_param_1\n      description: shared param 1 in ab\n      options: '[\"shared_param_1_ab_opt_1\", \"shared_param_1_ab_opt_2\"]'\n      rule-id: top_shared_rule_1\n  comp_ba:\n    - name: shared_param_1\n      description: shared param 1 in ba\n      options: '[\"shared_param_1_ba_opt_1\", \"shared_param_1_ba_opt_2\"]'\n      rule-id: top_shared_rule_1\n  comp_bb:\n    - name: shared_param_1\n      description: shared param 1 in bb\n      options: '[\"shared_param_1_bb_opt_1\", \"shared_param_1_bb_opt_2\"]'\n      rule-id: top_shared_rule_1\nx-trestle-comp-def-rules-param-vals:\n  # You may set new values for rule parameters by adding\n  #\n  # ssp-values:\n  #   - value 1\n  #   - value 2\n  #\n  # below a section of values:\n  # The values list refers to the values as set by the components, and the ssp-values are the new values\n  # to be placed in SetParameters of the SSP.\n  #\n  comp_aa:\n    - name: shared_param_1\n      values:\n        - shared_param_1_aa_opt_1\n      ssp-values:\n        - shared_param_1_aa_opt_2\n  comp_ab:\n    - name: shared_param_1\n      values:\n        - shared_param_1_ab_opt_2\nx-trestle-set-params:\n  # You may set values for parameters in the assembled SSP by adding\n  #\n  # ssp-values:\n  #   - value 1\n  #   - value 2\n  #\n  # below a section of values:\n  # The values list refers to the values in the resolved profile catalog, and the ssp-values represent new values\n  # to be placed in SetParameters of the SSP.\n  #\n  ac-1_prm_1:\n    values:\n      - comp_prof val 1\n    display-name: AC-1 (a) (1)\n  ac-1_prm_2:\n    values:\n  ac-1_prm_3:\n    values:\n  ac-1_prm_4:\n    values:\n  ac-1_prm_5:\n    values:\n  ac-1_prm_6:\n    values:\n  ac-1_prm_7:\n    values:\nx-trestle-global:\n  profile:\n    title: comp prof aa\n    href: trestle://profiles/comp_prof/profile.json\n  sort-id: ac-01\nx-trestle-add-props:\n  # Add or modify control properties here\n  # Properties may be at the control or part level\n  # Add control level properties like this:\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #\n  # Add properties to a statement part like this, where \"b.\" is the label of the target statement part\n  #   - name: ac1_new_prop\n  #     value: new property value\n  #     smt-part: b.\n  #\n  - name: prop_with_ns\n    value: prop with ns\n    ns: https://my_new_namespace\n  - name: prop_with_no_ns\n    value: prop with no ns\n    ns: https://my_added_namespace\n---\n\n# ac-1 - \\[Access Control\\] Policy and Procedures\n\n## Control Statement\n\nThe organization:\n\n- \\[a.\\] Develop, document, and disseminate to [comp_prof val 1]:\n\n  - \\[1.\\] [Organization-level; Mission/business process-level; System-level] access control policy that:\n\n    - \\[(a)\\] Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and\n    - \\[(b)\\] Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and\n\n  - \\[2.\\] Procedures to facilitate the implementation of the access control policy and the associated access controls;\n\n- \\[b.\\] Designate an [organization-defined official] to manage the development, documentation, and dissemination of the access control policy and procedures; and\n\n- \\[c.\\] Review and update the current access control:\n\n  - \\[1.\\] Policy [organization-defined frequency] and following [organization-defined events]; and\n  - \\[2.\\] Procedures [organization-defined frequency] and following [organization-defined events].\n\n## Control guidance\n\nAccess control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. Policies and procedures contribute to security and privacy assurance. Therefore, it is important that security and privacy programs collaborate on the development of access control policy and procedures. Security and privacy program policies and procedures at the organization level are preferable, in general, and may obviate the need for mission- or system-specific policies and procedures. The policy can be included as part of the general security and privacy policy or be represented by multiple policies reflecting the complex nature of organizations. Procedures can be established for security and privacy programs, for mission or business processes, and for systems, if needed. Procedures describe how the policies or controls are implemented and can be directed at the individual or role that is the object of the procedure. Procedures can be documented in system security and privacy plans or in one or more separate documents. Events that may precipitate an update to access control policy and procedures include assessment or audit findings, security incidents or breaches, or changes in laws, executive orders, directives, regulations, policies, standards, and guidelines. Simply restating controls does not constitute an organizational policy or procedure.\n\n______________________________________________________________________\n\n## What is the solution and how is it implemented?\n\n<!-- For implementation status enter one of: implemented, partial, planned, alternative, not-applicable -->\n\n<!-- Note that the list of rules under ### Rules: is read-only and changes will not be captured after assembly to JSON -->\n\n### This System\n\n<!-- Add implementation prose for the main This System component for control: ac-1 -->\n\n#### Implementation Status: planned\n\n### comp_aa\n\nimp req prose for ac-1 from comp aa\n\n#### Rules:\n\n- top_shared_rule_1\n\n#### Implementation Status: implemented\n\n### comp_ab\n\n<!-- Add control implementation description here for control: ac-1 -->\n\n#### Rules:\n\n- top_shared_rule_1\n\n#### Implementation Status: implemented\n\n______________________________________________________________________\n\n## Implementation for part a.\n\n### comp_aa\n\nstatement prose for part a. from comp aa\n\n#### Rules:\n\n- comp_rule_aa_1\n\n#### Implementation Status: partial\n\n### comp_ab\n\n<!-- Add control implementation description here for item a. -->\n\n#### Rules:\n\n- comp_rule_ab_1\n\n#### Implementation Status: partial\n\n______________________________________________________________________\n

                                                                                    \\ Each label in the ssp is wrapped in \\[ \\] to indicate it comes directly from the label in the control and is not generated by the markdown viewer. Keep in mind that the actual label is the same but with the \\[ \\] removed.

                                                                                    Note that for each statement in the control description there is a corresponding response section in which to provide a detailed response for later inclusion in the final ssp as the control implementation.

                                                                                    Also note that the optional final sections are provided, and labeled using the title for the corresponding section.

                                                                                    In addition, this is the only control markdown where the moustache ({{}}) items have been replaced by the corresponding parameter values in the final resolved profile catalog, surrounded by brackets, so that the prose corresponds to the final intended control and its implementation.

                                                                                    The markdown can have guidance per-component in the control, as shown by the line, ### ACME Component. Any prose directly under a ## implementation section will apply to the overall system component, but sections in a sub-header of the form ### will only apply to that particular component.

                                                                                    The --include-all-parts flag controls how the main system component (This System) is written in the markdown. By default, control parts are not written out unless a component has a rule associated with that particular control part or statement. When --include-all-parts is set, all control parts will be written with the main component present under the ## Implementation for part <part> section. All other components will still be conditionally added based on the presence of rules.

                                                                                    After generating the markdown for the resolved profile catalog you may then edit the files and provide text in the sections with Add control implementation... in them. But do not remove the horizontal rule lines or modify/remove the lines with ### in them, corresponding to system components.

                                                                                    If you edit the control markdown files you may run ssp-generate again and your edits will not be overwritten. When writing out the markdown for a control, any existing markdown for that control will be read and the response text for each part will be re-inserted into the new markdown file. If the new markdown has added parts the original responses will be placed correctly in the new file, but if any part is removed from the source control json file then any corresponding prose will be lost after the next ssp-generate.

                                                                                    The x-trestle-add-props key of the yaml header allows the addition of properties to the implemented requirements under the SSP control implementation, comprising name, value, and optionally a namespace ns value. Similarly to the x-trestle-add-props in profile authoring, the properties may be added at the control level, or attached to a top level statement part by adding a value, smt-part with value a., b. or any other label for one of the top level statement parts.

                                                                                    trestle author ssp-assemble

                                                                                    After manually edting the markdown and providing the responses for the control implementation requirements, the markdown can be assembled into a single json SSP file with:

                                                                                    trestle author ssp-assemble --markdown my_ssp --compdefs my_compdef_a,my_compdef_b --output my_json_ssp

                                                                                    This will assemble the markdown files in the my_ssp directory and create a json SSP with name my_json_ssp in the system-security-plans directory.

                                                                                    As indicated for ssp-generate, please do not alter any of the horizontal rule lines or lines indicating the part or control id, e.g. ### ACME Component. You may run ssp-generate and ssp-assemble repeatedly for the same markdown directory, allowing a continuous editing and updating cycle.

                                                                                    As with all the assemble tools, you may optionally specify a --name for a corresponding json file into which the updates will be inserted, thereby preserving metadata and other aspects of the model. The result can overwrite the provided model or get directed to a new model. And the version may be updated and the uuid's regenerated. As with the other -assemble tools, if an output file already exists, a new one will only be written if there are changes to the model relative to the existing file. See catalog-assemble for more details.

                                                                                    If you do not specify component-defintions during assembly, the markdown should not refer to any components other than This System. Thus you may first generate markdown with ssp-generate and no component-definitions specified - and then you may assemble that ssp with ssp-assemble and no component-definitions specified - but only if there are no components other than This System referenced in the markdown. You may add new component implementation details to the markdown later, but any new components must be defined in a component-defintion file, and that file must be specified when ssp-assemble is run.

                                                                                    ssp inheritance view

                                                                                    The inheritance view is generated by setting the --leveraged-ssp flag with trestle author ssp-generate. It contains information relating to exported information such as inherited capabilities and customer responsibilities that can be used to populate the inheritance information in the assembled SSP. When used, a directory named \"inheritance\" is created within the markdown directory. This directory serves as a designated space for mapping inherited capabilities and responsibilities onto components in the assemble SSP and authoring satisfied statements for responsibilities.

                                                                                    Example usage for creation of the markdown:

                                                                                    trestle author ssp-generate --profile my_prof --compdefs \"compdef_a,compdef_b\" --yaml /my_yaml_dir/header.yaml --leveraged-ssp my_provider_ssp --output my_ssp

                                                                                    In this example the leveraged ssp has previously been imported into the trestle directory, but it can be fetched from remote location.

                                                                                    The generated markdown output with the inheritance view will be placed in the trestle subdirectory my_ssp/inheritance with a subdirectory for each component in the leveraged ssp with directories separated by control and statement id below.

                                                                                    An example of this directory structure is below.

                                                                                    .\n\u251c\u2500\u2500 Application\n\u2502   \u251c\u2500\u2500 ac-1_stmt.a\n\u2502   \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001001002006.md\n\u2502   \u251c\u2500\u2500 ac-2.1\n\u2502   \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001001002004.md\n\u2502   \u2514\u2500\u2500 ac-2_stmt.a\n\u2502       \u2514\u2500\u2500 11111111-0000-4000-9009-002001002001_11111111-0000-4000-9009-002001002002.md\n\u2514\u2500\u2500 This System\n    \u251c\u2500\u2500 ac-1_stmt.a\n    \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001002002001.md\n    \u251c\u2500\u2500 ac-2.1\n    \u2502   \u2514\u2500\u2500 11111111-0000-4000-9009-001001002001.md\n    \u2514\u2500\u2500 ac-2_stmt.a\n        \u2514\u2500\u2500 11111111-0000-4000-9009-002001001001.md\n

                                                                                    The leveraged components are used as the top level directory to allow any non-leveraged components to be easily skipped or removed. Each markdown file is named in accordance with the uuid of the exported statement to ensure statement description updates can be applied.

                                                                                    There are three types of markdown files that can be generated from this process.

                                                                                    The examples below demonstrate these types:

                                                                                    Example of inheritance provided only markdown after ssp-generate
                                                                                    ---\nx-trestle-statement:\n  # Add or modify leveraged SSP Statements here.\n  provided-uuid: 11111111-0000-4000-9009-001002002001\nx-trestle-leveraging-comp:\n  # Leveraged statements can be optionally associated with components in this system.\n  # Associate leveraged statements to Components of this system here:\n  - name: REPLACE_ME\n---\n\n# Provided Statement Description\n\nCustomer_appropriate description of what may be inherited.\n
                                                                                    Example of inheritance customer responsibility only markdown after ssp-generate
                                                                                    ---\nx-trestle-statement:\n  # Add or modify leveraged SSP Statements here.\n  responsibility-uuid: 11111111-0000-4000-9009-002001001001\nx-trestle-leveraging-comp:\n  # Leveraged statements can be optionally associated with components in this system.\n  # Associate leveraged statements to Components of this system here:\n  - name: REPLACE_ME\n---\n\n# Responsibility Statement Description\n\nLeveraging system's responsibilities with respect to inheriting this capability.\n\n# Satisfied Statement Description\n\n<!-- Use this section to explain how the inherited responsibility is being satisfied. -->\n
                                                                                    Example of inheritance shared responsibility markdown after ssp-generate
                                                                                    ---\nx-trestle-statement:\n  # Add or modify leveraged SSP Statements here.\n  provided-uuid: 11111111-0000-4000-9009-002001002001\n  responsibility-uuid: 11111111-0000-4000-9009-002001002002\nx-trestle-leveraging-comp:\n  # Leveraged statements can be optionally associated with components in this system.\n  # Associate leveraged statements to Components of this system here:\n  - name: REPLACE_ME\n---\n\n# Provided Statement Description\n\nConsumer-appropriate description of what may be inherited.\n\n# Responsibility Statement Description\n\nLeveraging system's responsibilities with respect to inheriting this capability.\n\n# Satisfied Statement Description\n\n<!-- Use this section to explain how the inherited responsibility is being satisfied. -->\n

                                                                                    Some additional information and tips about this markdown are below:

                                                                                    • Do not change the statement UUIDs in the YAML header. This is used in the assembled JSON to link the statements in the leveraged SSP to the components in the leveraging SSP.
                                                                                    • When mapping components in the YAML header, use the component title. If you do not wish to map a component to a particular inherited capability or responsibility, just leave the file as is. Files without mapped components or that contain the default \"REPLACE ME\" entry will be skipped.
                                                                                    • If the file exists, just the editable information will be preserved when regenerating existing inheritance view markdown. This includes the information under Satisfied Statement Description and the mapped components in the YAML header.

                                                                                    After manually editing the inheritance view markdown, the trestle author ssp-assemble command can be run without modifications for the inheritance view use case. During assemble, the inheritance directory is detected and the information will be assembled into the SSP. The by-component assemblies will be updated or added under existing implemented requirement or statement sections with the information from the markdown.

                                                                                    trestle author ssp-filter

                                                                                    Once you have an SSP in the trestle directory you can filter its contents with a profile, list of components, list of implementation statuses, or list control origination values by using the command trestle author ssp-filter. The SSP is assumed to contain a superset of the controls needed by the profile if a profile is specified, and the filter operation will generate a new SSP with only those controls needed by the profile. If a list of component names is provided, only the specified components will appear in the system implementation of the ssp. If a list of implementation statuses is provided, controls with implementations including those statuses will appear in the control implementation of the ssp. Similarly, if a list of control origination values is provided, implemented requirements with a control origination property value included in the provided values will appear in the control implementation of the ssp.

                                                                                    The filter command is invoked as:

                                                                                    trestle author ssp-filter --name my_ssp --profile my_profile --components comp_a:comp_b --implementation-status \"planned,partial\" --control-origination \"customer-configured\" --output my_culled_ssp

                                                                                    The SSP must be present in the trestle workspace and, if filtering by profile, that profile must also be in the trestle workspace. This command will generate a new SSP in the workspace. If the profile makes reference to a control not in the SSP then the routine will fail with an error message. Similarly, if one of the components is not present in the ssp the routine will also fail. The implementation statuses must be one of the allowed values as defined in the OSCAL SSP JSON format reference. Those include the following: implemented, partial, planned, alternative, and not-applicable. If an invalid value is provided, an error is returned. The control origination values also must be one of the allowed values as defined in the OSCAL SSP JSON format reference. Those include the following: system-specific, inherited, customer-configured, customer-provided, and organization. If an invalid value is provided, an error is returned.

                                                                                    Summary of options used by the catalog, profile, component and ssp authoring tools.

                                                                                    The provided options for the generation and assembly of documents in the ssp workflow is rich and powerful, but can also be confusing. To help see how they all relate please consult the following diagram showing the required and optional command line arguments for each command. The checkboxes indicate required and the open circles represent optional.

                                                                                    The options shown are fairly consistent across the -generate and -assemble functions, but some clarification may be needed. For catalog-assemble and profile-assemble you have the option to use an existing json file as a parent model into which new content is inserted - in memory - and the final model may either be written back into that same json file, or a different one - based on --output. If you just want to keep editing and modifying the same original json file you can specify --name and --output to be the same, original json file. But you could also direct it to a new json file while still using an original file as the \"parent.\" A key benefit of referencing an original json file is the resuse of metadata and backmatter - along with everything else separate from the controls.

                                                                                    ssp-generate is special because it starts with a profile rather than an ssp, whereas catalog-generate and profile-generate both start with a parent model of the same type. Nonetheless, you still have an option during ssp-assemble to use a given json file as the template into which new content is inserted, and once again you may overwrite that original json file or direct it to a new one using --output.

                                                                                    "},{"location":"tutorials/task.csv-to-oscal-cd/transformation/","title":"Tutorial: Setup for and use of standard format csv-file to OSCAL Component Definition json-file transformer","text":"

                                                                                    Here are step by step instructions for setup and transformation of trestle standard format csv-file into OSCAL Component Definition json-file using the compliance-trestle tool.

                                                                                    "},{"location":"tutorials/task.csv-to-oscal-cd/transformation/#objective","title":"Objective","text":"

                                                                                    How to transform trestle standard format csv-file into a component-definition.json file.

                                                                                    There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from .csv to component-definition.json.

                                                                                    Table: expected .csv content

                                                                                    The below table represents the expectations of trestle task csv-to-oscal-cd for the contents of the input csv-file for synthesis of the output OSCAL Component Definition json-file.

                                                                                    Column Name is the name of the expected column in the input csv-file. Any additional columns not identified here, for example foobar, are also extracted and placed into the output json-file as component.control-implementation.prop[\"foobar\"].

                                                                                    Component Definition Locale is the path within the output json-file into witch the value is stashed.

                                                                                    Column Name Value Type Specification Value Description Component Definition Locale Example Value Rule_Id String required A textual label that uniquely identifies a policy (desired state) that can be used to reference it elsewhere in this or other documents. component.control-implementation.prop[\"Rule_Id\"] password_policy_min_length_characters Rule_Description String required A description of the policy (desired state) including information about its purpose and scope. component.control-implementation.prop[\"Rule_Description\"] Ensure password policy requires minimum length of 12 characters Profile_Reference_URL String required A URL reference to the source catalog or profile for which this component is implementing controls for. A profile designates a selection and configuration of controls from one or more catalogs component.control-implementation.source https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_HIGH-baseline_profile.json Profile_Description String required A description of the profile. component.control-implementation.description NIST Special Publication 800-53 Revision 5 HIGH IMPACT BASELINE Component_Type String required A category describing the purpose of the component. component.type Validation Control_Mappings String List (blank separated) required A list of textual labels that uniquely identify the controls or statements that the component implements. component.control-implementation.implemented-requirement.statement.statement-id*and*component.control-implementation.implemented-requirement.control-id ia-5.1_smt.a ia-5.1 Resource String required A human readable name for the component. component.title Compliance Center Parameter_Id String optional A textual label that uniquely identifies the parameter associated with that policy (desired state) or controls implemented by the policy (desired state). A description of the parameter including the purpose and use of the parameter. component.control-implementation.prop[\"Parameter_Id\"]*and*component.control-implementation.set-parameter.param-id minimum_password_length Parameter_Description String optional A description of the parameter including the purpose and use of the parameter. component.control-implementation.prop[\"Parameter_Description\"] Minimum Password Parameter_Default_Value String optional A value recommended in this profile for the parameter of the control or policy (desired state). component.control-implementation.set-parameter.values 12 Parameter_Value_Alternatives String List (blank separated) optional ONLY for the policy (desired state) parameters: A value or set of values the parameter can take. component.control-implementation.prop[\"Parameter_Value_Alternatives\"] 12 8 Check_Id String optional A textual label that uniquely identifies a check of the policy (desired state) that can be used to reference it elsewhere in this or other documents. component.control-implementation.prop[\"Check_Id\"] check_password_policy_min_length_characters Check_Description String optional A description of the check of the policy (desired state) including the method (interview or examine or test) and procedure details. component.control-implementation.prop[\"Check_Description\"] Check whether password policy requires minimum length of 12 characters Fetcher String optional A textual label that uniquely identifies a collector of the actual state (evidence) associated with the policy (desired state) that can be used to reference it elsewhere in this or other documents. component.control-implementation.prop[\"Fetcher\"] fetch_password_policy_min_length_characters Fetcher_Description String optional A description of the collector of the actual state (evidence) associated with the policy (desired state) including the method (interview or examine or API) and questionaire component.control-implementation.prop[\"Fetcher_Description\"] Fetch whether password policy requires minimum length of 12 characters Resource_Instance_Type String optional A textual label that uniquely identifies a resource (component) type from the resource instance id. This text is part of all instance ids of a particular resource at runtime. For example the text 'db2' is part of all instance ids of resource DB2. component.control-implementation.prop[\"Resource_Instance_Type\"] DB2"},{"location":"tutorials/task.csv-to-oscal-cd/transformation/#step-1-install-trestle-in-a-python-virtual-environment","title":"Step 1: Install trestle in a Python virtual environment","text":"

                                                                                    Follow the instructions here to install trestle in a virtual environment.

                                                                                    "},{"location":"tutorials/task.csv-to-oscal-cd/transformation/#step-2-transform-profile-data-cis-benchmarks","title":"Step 2: Transform profile data (CIS benchmarks)","text":"

                                                                                    Linux, Mac

                                                                                    Windows

                                                                                    Make these changes:

                                                                                    • use backslashes `\\` for file paths
                                                                                    • use `md` instead of mkdir -p
                                                                                    • put the url in double quotes for `curl`
                                                                                    • use `more` instead of cat
                                                                                    • Navigate to trestle workspace.
                                                                                    (venv.trestle)$ cd trestle.workspace\n
                                                                                    • View configuration information.
                                                                                    (venv.trestle)$ trestle task csv-to-oscal-cd -i\ntrestle.core.commands.task:101 WARNING: Config file was not configured with the appropriate section for the task: \"[task.csv-to-oscal-cd]\"\nHelp information for csv-to-oscal-cd task.\n\nPurpose: From csv produce OSCAL component_definition file.\n\n\nConfiguration flags sit under [task.csv-to-oscal-cd]:\n  title             = (required) the component definition title.\n  version           = (required) the component definition version.\n  csv-file          = (required) the path of the csv file.\n  required columns:   Rule_Id\n                      Rule_Description\n                      Profile_Reference_URL\n                      Profile_Description\n                      Component_Type\n                      Control_Mappings\n                      Resource\n  optional columns:   Parameter_Id\n                      Parameter_Description\n                      Parameter_Default_Value\n                      Parameter_Value_Alternatives\n                      Check_Id\n                      Check_Description\n                      Fetcher\n                      Fetcher_Description\n                      Resource_Instance_Type\n  output-dir        = (required) the path of the output directory for synthesized OSCAL .json files.\n  namespace         = (optional) the namespace for properties, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/cd\n  user-namespace    = (optional) the user-namespace for properties, e.g. https://oscal-compass.github.io/compliance-trestle/schemas/oscal/cd/user-defined\n  class.column-name = (optional) the class to associate with the specified column name, e.g. class.Rule_Id = scc_class\n  output-overwrite  = (optional) true [default] or false; replace existing output when true.\n
                                                                                    • Create data folder.
                                                                                    (venv.trestle)$ mkdir -p adjunct-data\n
                                                                                    • Fetch sample csv-file.
                                                                                    (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.csv-to-oscal-cd/ocp4-sample-input.csv' > adjunct-data/ocp4-sample-input.csv\n
                                                                                    • Fetch trestle task file.
                                                                                    (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.csv-to-oscal-cd/demo-csv-to-oscal-cd.config' > adjunct-data/task-files/demo-csv-to-oscal-cd.config\n
                                                                                    demo-csv-to-oscal-cd.config
                                                                                    [task.csv-to-oscal-cd]\n\ncsv-file = adjunct-data/ocp4-sample-input.csv\noutput-dir = component-definitions/ocp4-sample\ntitle = ocp4-sample\nversion = 1.0\n
                                                                                    • Perform and validate the transform.
                                                                                    (venv.trestle)$ trestle task csv-to-oscal-cd -c demo-csv-to-oscal-cd.config \ninput: adjunct-data/ocp4-sample-input.csv\noutput: component-definitions/ocp4-sample/component-definition.json\nTask: csv-to-oscal-cd executed successfully.\n
                                                                                    • View the generated OSCAL.
                                                                                    (venv.trestle)$ component-definitions/ocp4-sample/component-definition.json\n
                                                                                    component-definition.json
                                                                                    {\n  \"component-definition\": {\n    \"uuid\": \"83cc8984-b00a-4799-885c-60b689efebd0\",\n    \"metadata\": {\n      \"title\": \"ocp4-sample\",\n      \"last-modified\": \"2022-11-18T17:06:49+00:00\",\n      \"version\": \"1.0\",\n      \"oscal-version\": \"1.0.2\"\n    },\n    \"components\": [\n      {\n        \"uuid\": \"c0080494-186a-421d-9afd-f51e0359cbd8\",\n        \"type\": \"Service\",\n        \"title\": \"OSCO\",\n        \"description\": \"\",\n        \"control-implementations\": [\n          {\n            \"uuid\": \"43a69f86-a3ad-40fa-ada6-2f988b951728\",\n            \"source\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile\",\n            \"description\": \"ocp4\",\n            \"props\": [\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_anonymous_auth\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --anonymous-auth argument is set to false\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_anonymous_auth\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --anonymous-auth argument is set to false\",\n                \"remarks\": \"rule_set_0\"\n              },\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_basic_auth\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --basic-auth-file argument is not set\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_basic_auth\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --basic-auth-file argument is not set\",\n                \"remarks\": \"rule_set_1\"\n              },\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_token_auth\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --token-auth-file parameter is not set\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_token_auth\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --token-auth-file parameter is not set\",\n                \"remarks\": \"rule_set_2\"\n              },\n              {\n                \"name\": \"Rule_Id\",\n                \"value\": \"content_rule_api_server_https_for_kubelet_conn\",\n                \"remarks\": \"rule_set_3\"\n              },\n              {\n                \"name\": \"Rule_Description\",\n                \"value\": \"Ensure that the --kubelet-https argument is set to true\",\n                \"remarks\": \"rule_set_3\"\n              },\n              {\n                \"name\": \"Check_Id\",\n                \"value\": \"xccdf_org.ssgproject.content_rule_api_server_https_for_kubelet_conn\",\n                \"remarks\": \"rule_set_3\"\n              },\n              {\n                \"name\": \"Check_Description\",\n                \"value\": \"Ensure that the --kubelet-https argument is set to true\",\n                \"remarks\": \"rule_set_3\"\n              }\n            ],\n            \"implemented-requirements\": [\n              {\n                \"uuid\": \"c2893d38-1be4-4b0e-a090-96e846e15a3b\",\n                \"control-id\": \"CIS-1.2.1\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_anonymous_auth\"\n                  }\n                ]\n              },\n              {\n                \"uuid\": \"3c2f7129-9724-47c0-aadb-3b3c9c44995c\",\n                \"control-id\": \"CIS-1.2.2\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_basic_auth\"\n                  }\n                ]\n              },\n              {\n                \"uuid\": \"a4e2862f-7a1b-4182-b827-f5e797f589db\",\n                \"control-id\": \"CIS-1.2.3\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_token_auth\"\n                  }\n                ]\n              },\n              {\n                \"uuid\": \"daec13ab-829e-4dd6-a9d6-9ad18391681e\",\n                \"control-id\": \"CIS-1.2.4\",\n                \"description\": \"\",\n                \"props\": [\n                  {\n                    \"name\": \"Rule_Id\",\n                    \"value\": \"content_rule_api_server_https_for_kubelet_conn\"\n                  }\n                ]\n              }\n            ]\n          }\n        ]\n      }\n    ]\n  }\n}\n

                                                                                    Congratulations! You have completed this tutorial.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/","title":"Tutorial: Setup for and use of ComplianceAsCode profile to OSCAL Catalog transformer","text":"

                                                                                    Here are step by step instructions for setup and transformation of ComplianceAsCode profile data files into NIST standard OSCAL Catalog using the compliance-trestle tool.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/#objective","title":"Objective","text":"

                                                                                    How to transform one or more .profile compliance files into a standardized OSCAL.json file.

                                                                                    There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from .profile to OSCAL.json.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/#step-1-install-trestle-in-a-python-virtual-environment","title":"Step 1: Install trestle in a Python virtual environment","text":"

                                                                                    Follow the instructions here to install trestle in a virtual environment.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/#step-2-transform-profile-data-cis-benchmarks","title":"Step 2: Transform profile data (CIS benchmarks)","text":"

                                                                                    Linux, Mac

                                                                                    Windows

                                                                                    Make these changes:

                                                                                    • use backslashes `\\` for file paths
                                                                                    • use `md` instead of mkdir -p
                                                                                    • put the url in double quotes for `curl`
                                                                                    • use `more` instead of cat
                                                                                    • Navigate to trestle workspace.
                                                                                    (venv.trestle)$ cd trestle.workspace\n
                                                                                    • View configuration information.
                                                                                    (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-catalog -i\ntrestle.core.commands.task:102 WARNING: Config file was not configured with the appropriate section for the task: \"[task.ocp4-cis-profile-to-oscal-catalog]\"\nHelp information for ocp4-cis-profile-to-oscal-catalog task.\n\nPurpose: Create catalog from from standard (e.g. CIS benchmark).\n\nConfiguration flags sit under [task.ocp4-cis-profile-to-oscal-catalog]:\n  input-dir              = (required) location to read the compliance-as-code profile files.\n  output-dir             = (required) location to write the generated catalog.json file.\n  output-overwrite       = (optional) true [default] or false; replace existing output when true.\n
                                                                                    • Create data folders.
                                                                                    (venv.trestle)$ mkdir -p adjunct-data/cis-benchmarks\n(venv.trestle)$ mkdir -p adjunct-data/task-files\n
                                                                                    • Fetch ComplianceAsCode profile data.
                                                                                    (venv.trestle)$ curl 'https://raw.githubusercontent.com/ComplianceAsCode/content/master/products/ocp4/profiles/cis-node.profile' > adjunct-data/cis-benchmarks/cis-node.profile\n(venv.trestle)$ curl 'https://raw.githubusercontent.com/ComplianceAsCode/content/master/products/ocp4/profiles/cis-node.profile' > adjunct-data/cis-benchmarks/cis.profile\n
                                                                                    • Fetch trestle task file.
                                                                                    (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-catalog/demo-ocp4-cis-profile-to-oscal-catalog.config' > adjunct-data/task-files/demo-ocp4-cis-profile-to-oscal-catalog.config\n
                                                                                    demo-ocp4-cis-profile-to-oscal-catalog.config
                                                                                    [task.ocp4-cis-profile-to-oscal-catalog]\n\ninput-dir = adjunct-data/cis-benchmarks\noutput-dir = catalogs/ocp4-cis\n
                                                                                    • Perform and validate the transform.
                                                                                    (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-catalog -c adjunct-data/task-files/demo-ocp4-cis-profile-to-oscal-catalog.config\noutput: catalogs/ocp4-cis/catalog.json\nTask: ocp4-cis-profile-to-oscal-catalog executed successfully.\n\n(venv.trestle)$ trestle validate --all\nVALID: Model /home/<user>/trestle.workspace/catalogs/ocp4-cis/catalog.json passed the Validator to confirm the model passes all registered validation tests.\n
                                                                                    • View the generated OSCAL.
                                                                                    (venv.trestle)$ cat catlogs/ocp4-cis/catalog.json\n
                                                                                    catalog.json
                                                                                    {\n  \"catalog\": {\n    \"uuid\": \"19543ebf-4667-48b7-be47-d51154f16fda\",\n    \"metadata\": {\n      \"title\": \"CIS Red Hat OpenShift Container Platform 4 Benchmark\",\n      \"last-modified\": \"2021-12-03T13:52:21+00:00\",\n      \"version\": \"0.29.0\",\n      \"oscal-version\": \"1.0.0\",\n      \"links\": [\n        {\n          \"href\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis-node.profile\"\n        },\n        {\n          \"href\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile\"\n        }\n      ]\n    },\n    \"groups\": [\n      {\n        \"title\": \"1 Control Plane Components\",\n        \"groups\": [\n          {\n            \"title\": \"1.1 Master Node Configuration Files\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.1.1\",\n                \"title\": \"1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.2\",\n                \"title\": \"1.1.2 Ensure that the API server pod specification file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.3\",\n                \"title\": \"1.1.3 Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.4\",\n                \"title\": \"1.1.4 Ensure that the controller manager pod specification file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.5\",\n                \"title\": \"1.1.5 Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.6\",\n                \"title\": \"1.1.6 Ensure that the scheduler pod specification file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.7\",\n                \"title\": \"1.1.7 Ensure that the etcd pod specification file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.8\",\n                \"title\": \"1.1.8 Ensure that the etcd pod specification file ownership is set to root:root (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.1.9\",\n                \"title\": \"1.1.9 Ensure that the Container Network Interface file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.10\",\n                \"title\": \"1.1.10 Ensure that the Container Network Interface file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.11\",\n                \"title\": \"1.1.11 Ensure that the etcd data directory permissions are set to 700 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.12\",\n                \"title\": \"1.1.12 Ensure that the etcd data directory ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.13\",\n                \"title\": \"1.1.13 Ensure that the admin.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.14\",\n                \"title\": \"1.1.14 Ensure that the admin.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.15\",\n                \"title\": \"1.1.15 Ensure that the scheduler.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.16\",\n                \"title\": \"1.1.16 Ensure that the scheduler.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.17\",\n                \"title\": \"1.1.17 Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.18\",\n                \"title\": \"1.1.18 Ensure that the controller-manager.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.19\",\n                \"title\": \"1.1.19 Ensure that the OpenShift PKI directory and file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-1.1.20\",\n                \"title\": \"1.1.20 Ensure that the OpenShift PKI certificate file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-1.1.21\",\n                \"title\": \"1.1.21 Ensure that the OpenShift PKI key file permissions are set to 600\"\n              }\n            ]\n          },\n          {\n            \"title\": \"1.2 API Server\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.2.1\",\n                \"title\": \"1.2.1 Ensure that the --anonymous-auth argument is set to false\"\n              },\n              {\n                \"id\": \"CIS-1.2.2\",\n                \"title\": \"1.2.2 Ensure that the --basic-auth-file argument is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.3\",\n                \"title\": \"1.2.3 Ensure that the --token-auth-file parameter is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.4\",\n                \"title\": \"1.2.4 Ensure that the --kubelet-https argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.2.5\",\n                \"title\": \"1.2.5 Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.6\",\n                \"title\": \"1.2.6 Ensure that the --kubelet-certificate-authority argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.7\",\n                \"title\": \"1.2.7 Ensure that the --authorization-mode argument is not set to AlwaysAllow\"\n              },\n              {\n                \"id\": \"CIS-1.2.8\",\n                \"title\": \"1.2.8 Ensure that the --authorization-mode argument includes Node\"\n              },\n              {\n                \"id\": \"CIS-1.2.9\",\n                \"title\": \"1.2.9 Ensure that the --authorization-mode argument includes RBAC\"\n              },\n              {\n                \"id\": \"CIS-1.2.10\",\n                \"title\": \"1.2.10 Ensure that the admission control plugin EventRateLimit is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.11\",\n                \"title\": \"1.2.11 Ensure that the admission control plugin AlwaysAdmit is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.12\",\n                \"title\": \"1.2.12 Ensure that the admission control plugin AlwaysPullImages is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.13\",\n                \"title\": \"1.2.13 Ensure that the admission control plugin SecurityContextDeny is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.14\",\n                \"title\": \"1.2.14 Ensure that the admission control plugin ServiceAccount is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.15\",\n                \"title\": \"1.2.15 Ensure that the admission control plugin NamespaceLifecycle is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.16\",\n                \"title\": \"1.2.16 Ensure that the admission control plugin PodSecurityPolicy is set (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.2.17\",\n                \"title\": \"1.2.17 Ensure that the admission control plugin NodeRestriction is set (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.2.18\",\n                \"title\": \"1.2.18 Ensure that the --insecure-bind-address argument is not set\"\n              },\n              {\n                \"id\": \"CIS-1.2.19\",\n                \"title\": \"1.2.19 Ensure that the --insecure-port argument is set to 0\"\n              },\n              {\n                \"id\": \"CIS-1.2.20\",\n                \"title\": \"1.2.20 Ensure that the --secure-port argument is not set to 0\"\n              },\n              {\n                \"id\": \"CIS-1.2.21\",\n                \"title\": \"1.2.21 Ensure that the --profiling argument is set to false\"\n              },\n              {\n                \"id\": \"CIS-1.2.22\",\n                \"title\": \"1.2.22 Ensure that the --audit-log-path argument is set\"\n              },\n              {\n                \"id\": \"CIS-1.2.23\",\n                \"title\": \"1.2.23 Ensure that the audit logs are forwarded off the cluster for retention\"\n              },\n              {\n                \"id\": \"CIS-1.2.24\",\n                \"title\": \"1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.25\",\n                \"title\": \"1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.26\",\n                \"title\": \"1.2.26 Ensure that the --request-timeout argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.27\",\n                \"title\": \"1.2.27 Ensure that the --service-account-lookup argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.2.28\",\n                \"title\": \"1.2.28 Ensure that the --service-account-key-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.29\",\n                \"title\": \"1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.30\",\n                \"title\": \"1.2.30 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.31\",\n                \"title\": \"1.2.31 Ensure that the --client-ca-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.32\",\n                \"title\": \"1.2.32 Ensure that the --etcd-cafile argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.33\",\n                \"title\": \"1.2.33 Ensure that the --encryption-provider-config argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.2.34\",\n                \"title\": \"1.2.34 Ensure that encryption providers are appropriately configured\"\n              },\n              {\n                \"id\": \"CIS-1.2.35\",\n                \"title\": \"1.2.35 Ensure that the API Server only makes use of Strong Cryptographic Ciphers\"\n              }\n            ]\n          },\n          {\n            \"title\": \"1.3 Controller Manager\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.3.1\",\n                \"title\": \"1.3.1 Ensure that garbage collection is configured as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.3.2\",\n                \"title\": \"1.3.2 Ensure that controller manager healthz endpoints are protected by RBAC. (Automated)\"\n              },\n              {\n                \"id\": \"CIS-1.3.3\",\n                \"title\": \"1.3.3 Ensure that the --use-service-account-credentials argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.3.4\",\n                \"title\": \"1.3.4 Ensure that the --service-account-private-key-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.3.5\",\n                \"title\": \"1.3.5 Ensure that the --root-ca-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-1.3.6\",\n                \"title\": \"1.3.6 Ensure that the RotateKubeletServerCertificate argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-1.3.7\",\n                \"title\": \"1.3.7 Ensure that the --bind-address argument is set to 127.0.0.1\"\n              }\n            ]\n          },\n          {\n            \"title\": \"1.4 Scheduler\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-1.4.1\",\n                \"title\": \"1.4.1 Ensure that the --profiling argument is set to false  (info only)\"\n              },\n              {\n                \"id\": \"CIS-1.4.2\",\n                \"title\": \"1.4.2 Ensure that the --bind-address argument is set to 127.0.0.1\"\n              }\n            ]\n          }\n        ]\n      },\n      {\n        \"title\": \"2 etcd\",\n        \"controls\": [\n          {\n            \"id\": \"CIS-2.1\",\n            \"title\": \"2.1 Ensure that the --cert-file and --key-file arguments are set as appropriate\"\n          },\n          {\n            \"id\": \"CIS-2.2\",\n            \"title\": \"2.2 Ensure that the --client-cert-auth argument is set to true\"\n          },\n          {\n            \"id\": \"CIS-2.3\",\n            \"title\": \"2.3 Ensure that the --auto-tls argument is not set to true\"\n          },\n          {\n            \"id\": \"CIS-2.4\",\n            \"title\": \"2.4 Ensure that the --peer-cert-file and --peer-key-file arguments are set as appropriate\"\n          },\n          {\n            \"id\": \"CIS-2.5\",\n            \"title\": \"2.5 Ensure that the --peer-client-cert-auth argument is set to true\"\n          },\n          {\n            \"id\": \"CIS-2.6\",\n            \"title\": \"2.6 Ensure that the --peer-auto-tls argument is not set to true\"\n          },\n          {\n            \"id\": \"CIS-2.7\",\n            \"title\": \"2.7 Ensure that a unique Certificate Authority is used for etcd\"\n          }\n        ]\n      },\n      {\n        \"title\": \"3 Control Plane Configuration\",\n        \"groups\": [\n          {\n            \"title\": \"3.1 Authentication and Authorization\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-3.1.1\",\n                \"title\": \"3.1.1 Client certificate authentication should not be used for users\"\n              }\n            ]\n          },\n          {\n            \"title\": \"3.2 Logging\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-3.2.1\",\n                \"title\": \"3.2.1 Ensure that a minimal audit policy is created\"\n              },\n              {\n                \"id\": \"CIS-3.2.2\",\n                \"title\": \"3.2.2 Ensure that the audit policy covers key security concerns\"\n              }\n            ]\n          }\n        ]\n      },\n      {\n        \"title\": \"4 Worker Nodes\",\n        \"groups\": [\n          {\n            \"title\": \"4.1 Worker node configuration\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-4.1.1\",\n                \"title\": \"4.1.1 Ensure that the kubelet service file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.2\",\n                \"title\": \"4.1.2 Ensure that the kubelet service file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-4.1.3\",\n                \"title\": \"4.1.3 If proxy kubeconfig file exists ensure permissions are set to 644 or more restrictive (Automated)\"\n              },\n              {\n                \"id\": \"CIS-4.1.4\",\n                \"title\": \"4.1.4 If proxy kubeconfig file exists ensure ownership is set to root:root (Manual)\"\n              },\n              {\n                \"id\": \"CIS-4.1.5\",\n                \"title\": \"4.1.5 Ensure that the --kubeconfig kubelet.conf file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.6\",\n                \"title\": \"4.1.6 Ensure that the --kubeconfig kubelet.conf file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-4.1.7\",\n                \"title\": \"4.1.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.8\",\n                \"title\": \"4.1.8 Ensure that the client certificate authorities file ownership is set to root:root\"\n              },\n              {\n                \"id\": \"CIS-4.1.9\",\n                \"title\": \"4.1.9 Ensure that the kubelet --config configuration file has permissions set to 644 or more restrictive\"\n              },\n              {\n                \"id\": \"CIS-4.1.10\",\n                \"title\": \"4.1.10 Ensure that the kubelet configuration file ownership is set to root:root\"\n              }\n            ]\n          },\n          {\n            \"title\": \"4.2 Kubelet\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-4.2.1\",\n                \"title\": \"4.2.1 Ensure that the --anonymous-auth argument is set to false\"\n              },\n              {\n                \"id\": \"CIS-4.2.2\",\n                \"title\": \"4.2.2 Ensure that the --authorization-mode argument is not set to AlwaysAllow\"\n              },\n              {\n                \"id\": \"CIS-4.2.3\",\n                \"title\": \"4.2.3 Ensure that the --client-ca-file argument is set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-4.2.4\",\n                \"title\": \"4.2.4 Ensure that the --read-only-port argument is set to 0\"\n              },\n              {\n                \"id\": \"CIS-4.2.5\",\n                \"title\": \"4.2.5 Ensure that the --streaming-connection-idle-timeout argument is not set to 0\"\n              },\n              {\n                \"id\": \"CIS-4.2.6\",\n                \"title\": \"4.2.6 Ensure that the --protect-kernel-defaults argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-4.2.7\",\n                \"title\": \"4.2.7 Ensure that the --make-iptables-util-chains argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-4.2.8\",\n                \"title\": \"4.2.8 Ensure that the --hostname-override argument is not set\"\n              },\n              {\n                \"id\": \"CIS-4.2.9\",\n                \"title\": \"4.2.9 Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture\"\n              },\n              {\n                \"id\": \"CIS-4.2.10\",\n                \"title\": \"4.2.10 Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate\"\n              },\n              {\n                \"id\": \"CIS-4.2.11\",\n                \"title\": \"4.2.11 Ensure that the --rotate-certificates argument is not set to false\"\n              },\n              {\n                \"id\": \"CIS-4.2.12\",\n                \"title\": \"4.2.12 Verify that the RotateKubeletServerCertificate argument is set to true\"\n              },\n              {\n                \"id\": \"CIS-4.2.13\",\n                \"title\": \"4.2.13 Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers\"\n              }\n            ]\n          }\n        ]\n      },\n      {\n        \"title\": \"5 Policies\",\n        \"groups\": [\n          {\n            \"title\": \"5.1 RBAC and Service Accounts\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.1.1\",\n                \"title\": \"5.1.1 Ensure that the cluster-admin role is only used where required\"\n              },\n              {\n                \"id\": \"CIS-5.1.2\",\n                \"title\": \"5.1.2 Minimize access to secrets (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.3\",\n                \"title\": \"5.1.3 Minimize wildcard use in Roles and ClusterRoles (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.4\",\n                \"title\": \"5.1.4 Minimize access to create pods (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.5\",\n                \"title\": \"5.1.5 Ensure that default service accounts are not actively used. (info)\"\n              },\n              {\n                \"id\": \"CIS-5.1.6\",\n                \"title\": \"5.1.6 Ensure that Service Account Tokens are only mounted where necessary (info)\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.2 Pod Security Policies / Security Context Constraints\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.2.1\",\n                \"title\": \"5.2.1 Minimize the admission of privileged containers (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.2\",\n                \"title\": \"5.2.2 Minimize the admission of containers wishing to share the host process ID namespace (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.3\",\n                \"title\": \"5.2.3 Minimize the admission of containers wishing to share the host IPC namespace (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.4\",\n                \"title\": \"5.2.4 Minimize the admission of containers wishing to share the host network namespace (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.5\",\n                \"title\": \"5.2.5 Minimize the admission of containers with allowPrivilegeEscalation (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.6\",\n                \"title\": \"5.2.6 Minimize the admission of root containers (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.7\",\n                \"title\": \"5.2.7 Minimize the admission of containers with the NET_RAW capability (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.8\",\n                \"title\": \"5.2.8 Minimize the admission of containers with added capabilities (info)\"\n              },\n              {\n                \"id\": \"CIS-5.2.9\",\n                \"title\": \"5.2.9 Minimize the admission of containers with capabilities assigned (info)\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.3 Network Policies and CNI\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.3.1\",\n                \"title\": \"5.3.1 Ensure that the CNI in use supports Network Policies (info)\"\n              },\n              {\n                \"id\": \"CIS-5.3.2\",\n                \"title\": \"5.3.2 Ensure that all Namespaces have Network Policies defined\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.4 Secrets Management\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.4.1\",\n                \"title\": \"5.4.1 Prefer using secrets as files over secrets as environment variables (info)\"\n              },\n              {\n                \"id\": \"CIS-5.4.2\",\n                \"title\": \"5.4.2 Consider external secret storage (info)\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.5 Extensible Admission Control\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.5.1\",\n                \"title\": \"5.5.1 Configure Image Provenance using ImagePolicyWebhook admission controller\"\n              }\n            ]\n          },\n          {\n            \"title\": \"5.6 General Policies\",\n            \"controls\": [\n              {\n                \"id\": \"CIS-5.6.1\",\n                \"title\": \"5.6.1 Create administrative boundaries between resources using namespaces (info)\"\n              },\n              {\n                \"id\": \"CIS-5.6.2\",\n                \"title\": \"5.6.2 Ensure Seccomp Profile Pod Definitions (info)\"\n              },\n              {\n                \"id\": \"CIS-5.6.3\",\n                \"title\": \"5.6.3 Apply Security Context to your Pods and Containers (info)\"\n              },\n              {\n                \"id\": \"CIS-5.6.4\",\n                \"title\": \"5.6.4 The Default Namespace should not be used (info)\"\n              }\n            ]\n          }\n        ]\n      }\n    ]\n  }\n}\n

                                                                                    Congratulations! You have completed this tutorial.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/","title":"Tutorial: Setup for and use of ComplianceAsCode profile to OSCAL Component Definition transformer","text":"

                                                                                    Here are step by step instructions for setup and transformation of ComplianceAsCode profile data files into NIST standard OSCAL Component Definition using the compliance-trestle tool.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/#objective","title":"Objective","text":"

                                                                                    How to transform one or more .profile compliance files into a standardized OSCAL.json file.

                                                                                    There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from .profile to OSCAL.json.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/#step-1-install-trestle-in-a-python-virtual-environment","title":"Step 1: Install trestle in a Python virtual environment","text":"

                                                                                    Follow the instructions here to install trestle in a virtual environment.

                                                                                    "},{"location":"tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/#step-2-transform-profile-data-cis-benchmarks","title":"Step 2: Transform profile data (CIS benchmarks)","text":"

                                                                                    Linux, Mac

                                                                                    Windows

                                                                                    Make these changes:

                                                                                    • use backslashes `\\` for file paths
                                                                                    • use `md` instead of mkdir -p
                                                                                    • put the url in double quotes for `curl`
                                                                                    • use `more` instead of cat
                                                                                    • Navigate to trestle workspace.
                                                                                    (venv.trestle)$ cd trestle.workspace\n
                                                                                    • View configuration information.
                                                                                    (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-cd -i\ntrestle.core.commands.task:99 WARNING: Config file was not configured with the appropriate section for the task: \"[task.ocp4-cis-profile-to-oscal-cd]\"\nHelp information for ocp4-cis-profile-to-oscal-cd task.\n\nPurpose: Create component definition from standard (e.g. CIS benchmark).\n\nConfiguration flags sit under [task.ocp4-cis-profile-to-oscal-cd]:\n  component-name         = component name, e.g. OSCO.\n  org-name               = organization name, e.g. International Business Machines.\n  org-remarks            = organization remarks, e.g. IBM.\n  folder-cac             = folder containing compliance-as-code artifacts, e.g adjunct-data/cis-benchmarks/content.\n  output-dir             = location to write the generated component-definition.json file.\n  profile-name           = profile name, e.g. OCP4 CIS-benchmark v4.\n  profile-mnemonic       = profile mnemonic, e.g. ocp4-cis-node.\n  profile-ns             = profile ns, e.g. http://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud.\n  profile-version        = profile version, e.g. 1.1.\n  profile-check-version  = profile check version, e.g. 0.1.58.\n  profile-type           = profile type, e.g. OCP4.\n  profile-list           = profile list is blank separated list of \"<suffix>\" for config entries: profile-file.<suffix>, profile-title.<suffix>, profile-url.<suffix>, e.g. cis cis-node.\n  profile-file.<suffix>  = path of the profile file to ingest, e.g. ${folder-cac}/products/ocp4/profiles/cis-node.profile.\n  profile-title.<suffix> = title of the profile, e.g. CIS Red Hat OpenShift Container Platform 4 Benchmark.\n  profile-url.<suffix>   = URL of the profile, e.g. https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile.\n  rule-to-parameters-map = map file for set-parameters, e.g. adjunct-data/task-files/rule2var.json.\n  selected-rules         = file with list of selected rules, e.g. adjunct-data/task-files/selected_rules.json.\n  enabled-rules          = file with list of enabled rules, e.g. adjunct-data/task-files/enabled_rules.json.\n\nNotes:\n1. If a control has selected rules but no enabled rules, then all those selected are included.\n2. If a control has selected and enabled rules, then only those enabled are included.\n3. If a control has no selected rules, then none are included regardless of enabled.\n
                                                                                    • Create data folders.
                                                                                    (venv.trestle)$ mkdir -p adjunct-data/cis-benchmarks\n(venv.trestle)$ mkdir -p adjunct-data/config-files\n(venv.trestle)$ mkdir -p adjunct-data/task-files\n
                                                                                    • Fetch ComplianceAsCode data.
                                                                                    (venv.trestle)$ cd adjunct-data/cis-benchmarks/\n(venv.trestle)$ git clone https://github.com/ComplianceAsCode/content.git\n(venv.trestle)$ cd -\n
                                                                                    • Fetch trestle config and task files.
                                                                                    (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-cd/demo-ocp4-cis-profile-to-oscal-cd.config' > adjunct-data/config-files/demo-ocp4-cis-profile-to-oscal-cd.config\n(venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-cd/selected_rules.json' > adjunct-data/task-files/selected_rules.json\n(venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/main/docs/tutorials/task.ocp4-cis-profile-to-oscal-cd/enabled_rules.json' > adjunct-data/task-files/enabled_rules.json\n
                                                                                    demo-ocp4-cis-profile-to-oscal-cd.config
                                                                                    [task.ocp4-cis-profile-to-oscal-cd]\n\ncomponent-name = OSCO\n\nfolder-cac = adjunct-data/cis-benchmarks/content\n\norg-name = International Business Machines\norg-remarks = IBM\n\noutput-dir = component-definitions/ocp4-cis\n\nprofile-name = OCP4 CIS-benchmark v4\nprofile-mnemonic = ocp4-cis-node\nprofile-ns = http://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\nprofile-version = 1.1\nprofile-check-version = 0.1.58\n\nprofile-type = OCP4\nprofile-list = cis-node cis\n\nprofile-file.cis-node = ${folder-cac}/products/ocp4/profiles/cis-node.profile\nprofile-url.cis-node = https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis-node.profile\nprofile-title.cis-node = CIS Red Hat OpenShift Container Platform 4 Benchmark\n\nprofile-file.cis = ${folder-cac}/products/ocp4/profiles/cis.profile\nprofile-url.cis = https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis.profile\nprofile-title.cis = CIS Red Hat OpenShift Container Platform 4 Benchmark\n\nselected-rules  = adjunct-data/task-files/selected_rules.json\nenabled-rules  = adjunct-data/task-files/enabled_rules.json\n
                                                                                    selected_rules.json
                                                                                    [\n\"file_permissions_kube_apiserver\",\n\"file_owner_kube_apiserver\",\n\"file_groupowner_kube_apiserver\"\n]\n
                                                                                    enabled_rules.json
                                                                                    [\n\"file_permissions_cni_conf\",\n\"file_permissions_multus_conf\",\n\"file_owner_cni_conf\",\n\"file_groupowner_cni_conf\",\n\"file_owner_multus_conf\",\n\"file_groupowner_multus_conf\",\n\"kubelet_eviction_thresholds_set_soft_memory_available\",\n\"kubelet_eviction_thresholds_set_soft_nodefs_available\",\n\"kubelet_eviction_thresholds_set_soft_nodefs_inodesfree\",\n\"kubelet_eviction_thresholds_set_soft_imagefs_available\",\n\"kubelet_eviction_thresholds_set_soft_imagefs_inodesfree\",\n\"kubelet_eviction_thresholds_set_hard_memory_available\",\n\"kubelet_eviction_thresholds_set_hard_nodefs_available\",\n\"kubelet_eviction_thresholds_set_hard_nodefs_inodesfree\",\n\"kubelet_eviction_thresholds_set_hard_imagefs_available\",\n\"kubelet_eviction_thresholds_set_hard_imagefs_inodesfree\",\n\"etcd_unique_ca\",\n\"file_permissions_kubelet_conf\",\n\"file_groupowner_kubelet_conf\",\n\"file_owner_kubelet_conf\",\n\"file_permissions_worker_ca\",\n\"file_owner_worker_ca\",\n\"file_groupowner_worker_ca\",\n\"kubelet_anonymous_auth\",\n\"kubelet_configure_client_ca\",\n\"kubelet_enable_streaming_connections\",\n\"kubelet_enable_iptables_util_chains\",\n\"kubelet_disable_hostname_override\",\n\"kubelet_configure_event_creation\",\n\"kubelet_configure_tls_cipher_suites\"\n]\n
                                                                                    • Perform and validate the transform.
                                                                                    (venv.trestle)$ trestle task ocp4-cis-profile-to-oscal-cd -c adjunct-data/config-files/demo-ocp4-cis-profile-to-oscal-cd.config\noutput: component-definitions/ocp4-cis/component-definition.json\nTask: ocp4-cis-profile-to-oscal-cd executed successfully.\n\n(venv.trestle)$ trestle validate --all\nVALID: Model /home/<user>/trestle.workspace/component-definitions/ocp4-cis/component-definition.json passed the Validator to confirm the model passes all registered validation tests.\n
                                                                                    • View the generated OSCAL.
                                                                                    (venv.trestle)$ cat component-definitions/ocp4-cis/component-definition.json\n
                                                                                    component-definition.json
                                                                                    {\n\"component-definition\": {\n\"uuid\": \"d1b961ee-188b-42b9-943d-e11dc260f9dc\",\n\"metadata\": {\n\"title\": \"Component definition for OCP4 profiles\",\n\"last-modified\": \"2022-01-06T22:43:59+00:00\",\n\"version\": \"0.33.0\",\n\"oscal-version\": \"1.0.0\",\n\"roles\": [\n{\n\"id\": \"prepared-by\",\n\"title\": \"Indicates the organization that created this content.\"\n},\n{\n\"id\": \"prepared-for\",\n\"title\": \"Indicates the organization for which this content was created..\"\n},\n{\n\"id\": \"content-approver\",\n\"title\": \"Indicates the organization responsible for all content represented in the \\\"document\\\".\"\n}\n],\n\"parties\": [\n{\n\"uuid\": \"d00dff65-e4ae-4344-a206-1e298eff9066\",\n\"type\": \"organization\",\n\"name\": \"International Business Machines\",\n\"remarks\": \"IBM\"\n},\n{\n\"uuid\": \"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"type\": \"organization\",\n\"name\": \"Customer\",\n\"remarks\": \"organization to be customized at account creation only for their Component Definition\"\n},\n{\n\"uuid\": \"150f9eb7-7fa5-4989-b9be-bc3cba220354\",\n\"type\": \"organization\",\n\"name\": \"ISV\",\n\"remarks\": \"organization to be customized at ISV subscription only for their Component Definition\"\n}\n],\n\"responsible-parties\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n},\n\"components\": [\n{\n\"uuid\": \"e2ee2b93-6103-42de-b615-65b0b3ff2dc4\",\n\"type\": \"Service\",\n\"title\": \"OSCO\",\n\"description\": \"OSCO\",\n\"control-implementations\": [\n{\n\"uuid\": \"f9c2699a-2d2c-4ee2-87f3-042d1a9b3a79\",\n\"source\": \"https://github.com/ComplianceAsCode/content/blob/master/products/ocp4/profiles/cis-node.profile\",\n\"description\": \"OSCO implemented controls for CIS Red Hat OpenShift Container Platform 4 Benchmark.\",\n\"props\": [\n{\n\"name\": \"profile_name\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"OCP4 CIS-benchmark v4\",\n\"class\": \"scc_profile_name\"\n},\n{\n\"name\": \"profile_mnemonic\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"ocp4-cis-node\",\n\"class\": \"scc_profile_mnemonic\"\n},\n{\n\"name\": \"profile_version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"1.1\",\n\"class\": \"scc_profile_version\"\n},\n{\n\"name\": \"profile_check_version\",\n\"value\": \"0.1.58\"\n}\n],\n\"implemented-requirements\": [\n{\n\"uuid\": \"97142b13-bc30-4e72-be7f-36de9149a679\",\n\"control-id\": \"CIS-1.1.1\",\n\"description\": \"Ensure that the API server pod specification file permissions are set to 644 or more restrictive\",\n\"props\": [\n{\n\"name\": \"XCCDF_rule\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"xccdf_org.ssgproject.content_rule_file_permissions_kube_apiserver\",\n\"class\": \"scc_goal_name_id\",\n\"remarks\": \"Verify Permissions on the Kubernetes API Server Pod Specification File\"\n}\n],\n\"responsible-roles\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n},\n{\n\"uuid\": \"0690e2a7-b228-4954-93fe-c1d55936cfa8\",\n\"control-id\": \"CIS-1.1.2\",\n\"description\": \"Ensure that the API server pod specification file ownership is set to root:root\",\n\"props\": [\n{\n\"name\": \"XCCDF_rule\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"xccdf_org.ssgproject.content_rule_file_owner_kube_apiserver\",\n\"class\": \"scc_goal_name_id\",\n\"remarks\": \"Verify User Who Owns The Kubernetes API Server Pod Specification File\"\n}\n],\n\"responsible-roles\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n},\n{\n\"uuid\": \"18c61fb2-8603-440d-9d9a-8d6d1e232cd3\",\n\"control-id\": \"CIS-1.1.2\",\n\"description\": \"Ensure that the API server pod specification file ownership is set to root:root\",\n\"props\": [\n{\n\"name\": \"XCCDF_rule\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ibm-cloud\",\n\"value\": \"xccdf_org.ssgproject.content_rule_file_groupowner_kube_apiserver\",\n\"class\": \"scc_goal_name_id\",\n\"remarks\": \"Verify Group Who Owns The Kubernetes API Server Pod Specification File\"\n}\n],\n\"responsible-roles\": [\n{\n\"role-id\": \"prepared-by\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n},\n{\n\"role-id\": \"prepared-for\",\n\"party-uuids\": [\n\"851b55f0-5ba6-4684-8a48-5dad22ba2625\",\n\"150f9eb7-7fa5-4989-b9be-bc3cba220354\"\n]\n},\n{\n\"role-id\": \"content-approver\",\n\"party-uuids\": [\n\"d00dff65-e4ae-4344-a206-1e298eff9066\"\n]\n}\n]\n}\n]\n}\n]\n}\n]\n}\n}\n

                                                                                    Congratulations! You have completed this tutorial.

                                                                                    "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/","title":"Tutorial: Setup for and use of Tanium to OSCAL transformer","text":"

                                                                                    Here are step by step instructions for setup and transformation of Tanium compliance data files into NIST standard OSCAL using the compliance-trestle tool.

                                                                                    "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/#objective","title":"Objective","text":"

                                                                                    How to transform a Tanium.results compliance file into a standardized OSCAL.json file.

                                                                                    There are 2 short steps shown below. The first is a one-time check/set-up of your environment. The second is a one-command transformation from Tanium.results to OSCAL.json.

                                                                                    "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/#step-1-environment-setup","title":"Step 1: Environment setup","text":"

                                                                                    Linux, Mac

                                                                                    Windows

                                                                                    Make these changes:

                                                                                    • use backslashes `\\` for file paths
                                                                                    • use `md` instead of mkdir -p
                                                                                    • put the url in double quotes for `curl`
                                                                                    • use `more` instead of cat
                                                                                    • Insure you have a modern Python (3.7, 3.8, 3.9).
                                                                                    $ python -V\nPython 3.8.3\n
                                                                                    • Setup a virtual environment.
                                                                                    $ cd\n$ python -m venv venv.trestle\n$ source venv.trestle/bin/activate\n(venv.trestle)$\n
                                                                                    • Insure you have a modern pip (19.x or greater).
                                                                                    (venv.trestle)$ pip --version\npip 19.2.3 from /home...\n
                                                                                    • Install compliance-trestle.
                                                                                    (venv.trestle)$ pip install compliance-trestle\nLooking in indexes: https://pypi.org/simple,...\n
                                                                                    • Check trestle viability (and view help).
                                                                                    (venv.trestle)$ trestle -h\nusage: trestle [-h] {init,create,split,merge,replicate,add,remove,validate,import,task,assemble} ...\n
                                                                                    • Create trestle workspace.
                                                                                    (venv.trestle)$ mkdir trestle.workspace\n(venv.trestle)$ cd trestle.workspace\n(venv.trestle)$ trestle init\nInitialized trestle project successfully in /home/<user>/trestle.workspace\n
                                                                                    "},{"location":"tutorials/task.tanium-result-to-oscal-ar/transformation/#step-2-transform-sample","title":"Step 2: Transform sample","text":"
                                                                                    • Create Tanium data folders.
                                                                                    (venv.trestle)$ mkdir -p tanium/tests/data/tasks/tanium/input\n
                                                                                    • Fetch sample Tanium data file. It is a \"raw\" Tanium result for which a transformation to OSCAL is desired.
                                                                                    (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/develop/tests/data/tasks/tanium/input-doc/Tanium.doc-json' > tanium/tests/data/tasks/tanium/input/Tanium.doc-json\n
                                                                                    sample: Tanium.doc-json
                                                                                    {\n\"Computer Name\": \"RHEL8\",\n\"Tanium Client IP Address\": \"192.168.0.125\",\n\"IP Address\": [\n\"192.168.0.125\",\n\"192.168.122.1\",\n\"fe80::3c47:1aff:fe33:601\"\n],\n\"Comply - Compliance Findings\": [\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"State\": \"pass\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"State\": \"fail\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\"\n},\n{\n\"Check ID\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"State\": \"notchecked\",\n\"Rule ID\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\"\n}\n],\n\"Count\": \"1\"\n}\n
                                                                                    • Fetch sample trestle tanium-result-to-oscal-ar config file. It informs the trestle command where to read input and write output.
                                                                                    (venv.trestle)$ curl 'https://raw.githubusercontent.com/oscal-compass/compliance-trestle/develop/tests/data/tasks/tanium/demo-tanium-result-to-oscal-ar.config' > tanium/demo-tanium-result-to-oscal-ar.config\n
                                                                                    sample: demo-tanium-result-to-oscal-ar.config
                                                                                    [task.tanium-result-to-oscal-ar]\n\ninput-dir =  tests/data/tasks/tanium/input\noutput-dir = tests/data/tasks/tanium/runtime\n
                                                                                    • Perform the transform.
                                                                                    (venv.trestle)$ cd tanium\n(venv.trestle)$ trestle task tanium-result-to-oscal-ar -c demo-tanium-result-to-oscal-ar.config \ninput: tests/data/tasks/tanium/input/Tanium.doc-json\noutput: tests/data/tasks/tanium/runtime/Tanium.oscal.json\ninventory: 1\nobservations: 9\nTask: tanium-result-to-oscal-ar executed successfully.\n
                                                                                    • View the generated OSCAL.
                                                                                    (venv.trestle)$ cat tests/data/tasks/tanium/runtime/Tanium.oscal.json\n
                                                                                    sample: Tanium.oscal.json
                                                                                    {\n\"results\": [\n{\n\"uuid\": \"f79add8e-488a-45f3-9024-72ecf95c7952\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-05-12T13:46:46.000+00:00\",\n\"end\": \"2021-05-12T13:46:46.000+00:00\",\n\"local-definitions\": {\n\"components\": {\n\"1ea447fe-a2af-4110-baae-c70ed5223261\": {\n\"type\": \"Operating System\",\n\"title\": \"Red Hat Enterprise Linux 8\",\n\"description\": \"Red Hat Enterprise Linux 8\",\n\"status\": {\n\"state\": \"operational\"\n}\n}\n},\n\"inventory-items\": [\n{\n\"uuid\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"Computer Name\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"RHEL8\"\n},\n{\n\"name\": \"Tanium Client IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"192.168.0.125\",\n\"class\": \"scc_inventory_item_id\"\n},\n{\n\"name\": \"IP Address\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"['192.168.0.125', '192.168.122.1', 'fe80::3c47:1aff:fe33:601']\"\n},\n{\n\"name\": \"Count\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1\"\n}\n],\n\"implemented-components\": [\n{\n\"component-uuid\": \"1ea447fe-a2af-4110-baae-c70ed5223261\"\n}\n]\n}\n]\n},\n\"reviewed-controls\": {\n\"control-selections\": [\n{}\n]\n},\n\"observations\": [\n{\n\"uuid\": \"e67f5fd9-5b1f-4134-a67e-cebdc2e5735c\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.1_Ensure_mounting_of_cramfs_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"6cb81459-9c25-4a8b-bf3c-d8ff08ee728c\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.3_Ensure_mounting_of_squashfs_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"9453eaed-db41-4a20-b684-2887de2d9657\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_udf_filesystems_is_disabled\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"a37c2569-8695-4cfe-8b5c-bd8d6eaf9df7\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.10_Ensure_noexec_option_set_on_vartmp_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"b77e1b49-a818-4d43-adaf-69effcbd9219\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.14_Ensure_nodev_option_set_on_home_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"ac25b329-7a4a-45f4-b42b-1cce470e237b\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.15_Ensure_nodev_option_set_on_devshm_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"f9c0f033-f08b-431d-b411-fe1f63c2c98c\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.16_Ensure_nosuid_option_set_on_devshm_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"pass\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"149a814e-7f80-4e6d-a613-54f027e0d663\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.17_Ensure_noexec_option_set_on_devshm_partition\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"fail\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n},\n{\n\"uuid\": \"a0e602b5-e587-41c5-846b-675b26cf3e18\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"props\": [\n{\n\"name\": \"Check ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark;1.0.0-1;Level 1 - Server;1;xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\"\n},\n{\n\"name\": \"Check ID Benchmark\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"CIS Red Hat Enterprise Linux 8 Benchmark\",\n\"class\": \"scc_predefined_profile\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_check_version\"\n},\n{\n\"name\": \"Check ID Version\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"1.0.0-1\",\n\"class\": \"scc_predefined_profile_version\"\n},\n{\n\"name\": \"Check ID Level\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"Level 1 - Server\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"class\": \"scc_goal_description\"\n},\n{\n\"name\": \"Rule ID\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.18_Ensure_nodev_option_set_on_removable_media_partitions\",\n\"class\": \"scc_check_name_id\"\n},\n{\n\"name\": \"State\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"notchecked\",\n\"class\": \"scc_result\"\n},\n{\n\"name\": \"Timestamp\",\n\"ns\": \"https://oscal-compass.github.io/compliance-trestle/schemas/oscal/ar/tanium\",\n\"value\": \"2021-05-12T13:46:46+00:00\",\n\"class\": \"scc_timestamp\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2d33d2b0-af5c-4c37-85b1-e4f414183de2\",\n\"type\": \"inventory-item\"\n}\n],\n\"collected\": \"2021-05-12T13:46:46.000+00:00\"\n}\n],\n\"findings\": [\n{\n\"uuid\": \"00000000-0000-4000-8000-000000000000\",\n\"title\": \"No Finding.\",\n\"description\": \"No Finding.\"\n}\n]\n}\n]\n}\n

                                                                                    Congratulations! You have bridged Tanium data into an OSCAL Assessment Results using compliance-trestle.

                                                                                    Newtown, Victoria

                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/","title":"Tutorial: How to build an Oscal Assessment Results \"lite\" with Trestle SDK from your posture result format","text":"

                                                                                    The compliance-trestle (trestle) project provides helpful modules to assist your standardization efforts. Discussed below are some best practices for automated bridging to NIST OSCAL.

                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#why-nist-oscal","title":"Why NIST OSCAL?","text":"

                                                                                    The Open Security Controls Assessment Language OSCAL is a set of formats expressed in XML, JSON, and YAML that provide machine-readable representations of control catalogs, control baselines, system security plans, and assessment plans and results as adopted by the National Institute of Standards and Technology NIST.

                                                                                    Standardizing to OSCAL facilitates data interchange and understandability.

                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#objective","title":"Objective","text":"

                                                                                    The objective here is to transform your compliance data into valid OSCAL, in particular System Assessment Results SAR.

                                                                                    Examples of existing transformers included with trestle are for the OpenShift Compliance Operator OSCO and Tanium.

                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#overview","title":"Overview","text":"

                                                                                    You have a source of compliance data that is in non-OSCAL format (spreadsheet, XML, JSON, database, object-store...) and you would like to transform into standardized form in terms of NIST OSCAL. Presumed is an existing method for obtaining the compliance data from the cloud and materializing on disk as one or more files.

                                                                                    • Source files on disk (pink) is our starting point.
                                                                                    • OSCAL files on disk (blue) is our ending point.
                                                                                    • OSCAL object management and emitter Python code are provided by trestle (green).
                                                                                    • Transformation Python code (yellow) is to be written by you.

                                                                                    Other possible code stack configurations (not shown):

                                                                                    • write your own command module (file interface), but use trestle logic module (data processing)
                                                                                    • write your own command and logic modules, but rely on trestle OSCAL support and base

                                                                                    For example, one could create an auditree-arboretum harvest report (file interface) that employs the trestle xccdf-result-to-oscal-ar transformation (data processing) module.

                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#choose-mapping-strategy","title":"Choose Mapping Strategy","text":"

                                                                                    There are 3 potential levels of OSCAL Assessment Results that can be emitted by your transformer. From most complex to least complex they are:

                                                                                    • a complete SAR
                                                                                    • a partial SAR comprising Findings with Observations
                                                                                    • a partial SAR comprising Observations only

                                                                                    Below is a snippet from the SAR model with these three levels shown.

                                                                                    Although producing a complete SAR is possible, this transformation is not covered here. We focus on partial results, either Observations only or Observations with Findings.

                                                                                    Based on the data in hand from your compliance data source, and additional metadata that can be made available at the time of transformation, choose the best fit.

                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#observations-only","title":"Observations only","text":"

                                                                                    Emitting Observations only requires just rudimentary source data. For example, if each instance of source data includes not much more than:

                                                                                    • inventory-name: ssg-ocp4-ds-cis-111.222.333.444-pod
                                                                                    • rule-name: xccdf_org.ssgproject.content_rule_scheduler_profiling_argument
                                                                                    • rule-result: fail

                                                                                    then the best mapping would be to an Observations only.

                                                                                    example snippet: instance suitable for mapping to Observation
                                                                                    data: <rule-result idref=\"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\"\ntime=\"2020-08-03T02:26:26+00:00\" severity=\"low\" weight=\"1.000000\"> <result>fail</result>\n</rule-result>\nmetadata:\nname: ssg-ocp4-ds-cis-111.222.333.444-pod\n
                                                                                    example snippet: instance OSCAL Observation
                                                                                    {\n\"uuid\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"title\": \"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\",\n\"description\": \"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\",\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"56666738-0f9a-4e38-9aac-c0fad00a5821\",\n\"type\": \"component\",\n\"title\": \"Red Hat OpenShift Kubernetes\"\n},\n{\n\"uuid-ref\": \"46aADFAC-A1fd-4Cf0-a6aA-d1AfAb3e0d3e\",\n\"type\": \"inventory-item\",\n\"title\": \"Pod\",\n\"props\": [\n{\n\"name\": \"target\",\n\"value\": \"kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\"\n},\n{\n\"name\": \"cluster-name\",\n\"value\": \"ROKS-OpenSCAP-1\"\n},\n{\n\"name\": \"cluster-type\",\n\"value\": \"openshift\"\n},\n{\n\"name\": \"cluster-region\",\n\"value\": \"us-south\"\n}\n]\n}\n],\n\"relevant-evidence\": [\n{\n\"href\": \"https://github.mycorp.com/degenaro/evidence-locker\",\n\"description\": \"Evidence location.\",\n\"props\": [\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"id\",\n\"value\": \"xccdf_org.ssgproject.content_rule_scheduler_profiling_argument\"\n},\n{\n\"name\": \"time\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"timestamp\",\n\"value\": \"2020-08-03T02:26:26+00:00\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"result\",\n\"value\": \"fail\"\n},\n{\n\"name\": \"target\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"target\",\n\"value\": \"kube-br7qsa3d0vceu2so1a90-roksopensca-default-0000026b.iks.mycorp\"\n}\n]\n}\n]\n}\n
                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#findings-with-observations","title":"Findings with Observations","text":"

                                                                                    To additionally produce Findings, information about the controls associated with each rule-name is required. The control information can be part of the source data itself or can be provided as one or more supplemental metadata files.

                                                                                    If each instance of source data includes:

                                                                                    • inventory-name: cmp-wn-2115.demo.tanium.local
                                                                                    • rule-name: xccdf_org.cisecurity.benchmarks_rule_19.7.44.2.1_L2_Ensure_Prevent_Codec_Download_is_set_to_Enabled
                                                                                    • rule-result: fail
                                                                                    • control-name: 800-53: SC-18

                                                                                    then the best mapping wound be to Findings with Observations.

                                                                                    example snippet: xml instance suitable for mapping to Finding with Observation
                                                                                    {\n\"IP Address\": \"10.8.68.218\",\n\"Computer Name\": \"cmp-wn-2115.demo.tanium.local\",\n\"Comply - JovalCM Results[c2dc8749]\": [\n{\n\"Benchmark\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\",\n\"Benchmark Version\": \"1.5.0.1\",\n\"Profile\": \"Windows 10 - NIST 800-53\",\n\"ID\": \"xccdf_org.cisecurity.benchmarks_rule_19.7.44.2.1_L2_Ensure_Prevent_Codec_Download_is_set_to_Enabled\",\n\"Result\": \"fail\",\n\"Custom ID\": \"800-53: SC-18\",\n\"Version\": \"version: 1\"\n}\n],\n\"Count\": \"1\",\n\"Age\": \"600\"\n}\n
                                                                                    example snippet: instance OSCAL Finding
                                                                                    {\n\"findings\": [\n{\n\"uuid\": \"99c0a0de-e34e-4e22-95a1-1d4f24826565\",\n\"title\": \"800-53: IA-5\",\n\"description\": \"800-53: IA-5\",\n\"collected\": \"2021-03-16T13:29:14.000+00:00\",\n\"objective-status\": {\n\"props\": [\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"class\": \"source\",\n\"value\": \"NIST 800-53\"\n},\n{\n\"name\": \"id-ref\",\n\"ns\": \"dns://tanium\",\n\"class\": \"source\",\n\"value\": \"IA-5\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"STRVALUE\",\n\"value\": \"FAIL\"\n}\n],\n\"status\": \"not-satisfied\"\n},\n\"related-observations\": [\n{\n\"observation-uuid\": \"61092735-e365-4638-bc2c-ecd0ed407e73\"\n},\n{\n\"observation-uuid\": \"95a20b8e-ed0a-4b6c-bf87-8789265c7158\"\n}\n]\n}\n]\n}\n
                                                                                    example snippet: instance OSCAL Observation
                                                                                    {\n\"observations\": [\n{\n\"uuid\": \"61092735-e365-4638-bc2c-ecd0ed407e73\",\n\"description\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\",\n\"props\": [\n{\n\"name\": \"benchmark\",\n\"ns\": \"dns://tanium\",\n\"class\": \"source\",\n\"value\": \"CIS Microsoft Windows 10 Enterprise Release 1803 Benchmark\"\n},\n{\n\"name\": \"rule\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"id\",\n\"value\": \"xccdf_org.cisecurity.benchmarks_rule_1.1.1_L1_Ensure_Enforce_password_history_is_set_to_24_or_more_passwords\"\n},\n{\n\"name\": \"result\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"result\",\n\"value\": \"pass\"\n},\n{\n\"name\": \"time\",\n\"ns\": \"dns://xccdf\",\n\"class\": \"timestamp\",\n\"value\": \"2021-03-16T13:29:14+00:00\"\n}\n],\n\"methods\": [\n\"TEST-AUTOMATED\"\n],\n\"subjects\": [\n{\n\"uuid-ref\": \"2650b9ba-e767-4381-9a3f-127d1552d7d2\",\n\"type\": \"inventory-item\"\n}\n]\n}\n]\n}\n
                                                                                    example snippet: local definitions
                                                                                    {\n\"results\": [\n{\n\"uuid\": \"98028241-8705-4211-bf36-71e1f7aa6192\",\n\"title\": \"Tanium\",\n\"description\": \"Tanium\",\n\"start\": \"2021-03-16T13:29:14.000+00:00\",\n\"local-definitions\": {\n\"inventory-items\": [\n{\n\"uuid\": \"2650b9ba-e767-4381-9a3f-127d1552d7d2\",\n\"description\": \"inventory\",\n\"props\": [\n{\n\"name\": \"computer-name\",\n\"ns\": \"dns://tanium\",\n\"class\": \" inventory-item\",\n\"value\": \"cmp-wn-2106.demo.tanium.local\"\n},\n{\n\"name\": \"computer-ip\",\n\"ns\": \"dns://tanium\",\n\"class\": \" inventory-item\",\n\"value\": \"fe80::3cd5:564b:940e:49ab\"\n},\n{\n\"name\": \"profile\",\n\"ns\": \"dns://tanium\",\n\"class\": \" inventory-item\",\n\"value\": \"Windows 10\"\n}\n]\n}\n]\n}\n}\n]\n}\n
                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#implement-mapping-strategy","title":"Implement Mapping Strategy","text":"

                                                                                    The best practice for building a transformer is to employ layers. Recall that the top two layers (in yellow) are for you to implement, while the bottom two layers (in green) are provided by trestle to assist you.

                                                                                    Trestle is a Python based multi-faceted platform that simplifies this task by providing a set of Python classes which enforce adherence to the OSCAL schema, insuring that the produced OSCAL validates.

                                                                                    • file interfacing (read/write files)
                                                                                    • data processing (in-memory object structure construction)
                                                                                    • use of OSCAL versioned platform objects (trestle base and oscal functionality)
                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#file-interfacing","title":"File Interfacing","text":"

                                                                                    Write a command line tool, for example a trestle task or auditree-arboretum harvest report that:

                                                                                    • imports the commensurate data processing module
                                                                                    • reads the input
                                                                                    • send input to data processing module
                                                                                    • receives transformed data from data processing module
                                                                                    • writes the output
                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#data-processing","title":"Data Processing","text":"

                                                                                    Write a data processing module that receives data, and optionally metadata, for transformation from native form into OSCAL. Separation from the command line file read/write mechanism allows for module re-use.

                                                                                    The module should:

                                                                                    • import the trestle oscal module
                                                                                    • receive input data to be transformed
                                                                                    • receive metadata, optionally
                                                                                    • transform input into trestle oscal classes hierarchy
                                                                                    • send transformed OSCAL data in return

                                                                                    For the Observation only case, the transform is straight forward. Code should create one Observation for each rule/result pair.

                                                                                    For the Findings case, a bit more logic is required. Code should accumulate Observations for each Finding and determine an overall status for it. For example, if 15 Observations are found for Finding control AC-3, where 14 have result=PASS and 1 has result=FAIL, then the overall status for the Finding would be not satisfied with overall result=FAIL.

                                                                                    "},{"location":"tutorials/task.transformer-construction/transformer-construction/#examples","title":"Examples","text":"

                                                                                    There are 2 transformers in trestle. The xccdf-result-to-oscal-ar transformer emits OSCAL Observations, the simplest partial result.

                                                                                    The tanium-result-to-oscal-ar transformer emits OSCAL Findings, a more complex partial result.

                                                                                    Table of approximate lines of code.

                                                                                    task-name OSCAL type file interface data processing test cases xccdf-result-to-oscal-ar Observations only 275 350 400 tanum-to-oscal Findings, with Observations 200 350 300"},{"location":"tutorials/task.transformer-construction/transformer-construction/#contributing","title":"Contributing","text":"

                                                                                    Consider contributing your transformer to trestle or auditree-arboretum or other appropriate open source repository.

                                                                                    "}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index afa7684f3..0aa6da050 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,747 +2,747 @@ https://oscal-compass.github.io/compliance-trestle/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/cli/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/demonstrations-content/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/errors/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/license/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/maintainers/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/mkdocs_code_of_conduct/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/python_trestle_setup/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/trestle_author/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/trestle_author_jinja/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.cli/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.common_types/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.const/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.err/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.file_utils/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.list_utils/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.load_validate/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.log/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.model_utils/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.str_utils/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.trash/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.common.type_utils/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.all_validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.base_model/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.catalog.catalog_api/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.catalog.catalog_interface/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.catalog.catalog_merger/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.catalog.catalog_reader/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.catalog.catalog_writer/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.catalog_validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.add/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.assemble/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.catalog/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.command/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.common/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.component/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.consts/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.docs/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.folders/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.headers/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.jinja/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.prof/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.ssp/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.author.versioning.template_versioning/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.command_docs/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.common.cmd_utils/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.common.return_codes/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.create/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.describe/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.href/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.import_/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.init/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.merge/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.partial_object_validate/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.remove/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.replicate/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.split/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.task/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.validate/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.commands.version/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.control_context/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.control_interface/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.control_reader/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.control_writer/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.crm.bycomp_interface/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.crm.export_reader/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.crm.export_writer/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.crm.leveraged_statements/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.crm.ssp_inheritance_api/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.docs_control_writer/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.draw_io/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.duplicates_validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.generators/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.generic_oscal/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.jinja/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.links_validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.base_markdown_node/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.control_markdown_node/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.docs_markdown_node/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.markdown_api/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.markdown_const/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.markdown_processor/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.markdown_validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.markdown.md_writer/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.models.actions/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.models.elements/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.models.file_content_type/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.models.interfaces/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.models.plans/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.object_factory/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.parser/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.pipeline/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.profile_resolver/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.refs_validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.remote.cache/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.repository/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.resolver.merge/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.resolver.modify/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.resolver.prune/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.rule_parameters_validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.ssp_io/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.trestle_base_model/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.validator/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.core.validator_factory/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.assessment_plan/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.assessment_results/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.catalog/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.common/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.component/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.poam/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.profile/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.oscal.ssp/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.base_task/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.cis_xlsx_to_oscal_catalog/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.csv_to_oscal_cd/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_catalog/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.ocp4_cis_profile_to_oscal_cd/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.oscal_catalog_to_csv/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.oscal_profile_to_osco_profile/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.osco_result_to_oscal_ar/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.tanium_result_to_oscal_ar/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.transform/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.xccdf_result_to_oscal_ar/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.xlsx_helper/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.xlsx_to_oscal_cd/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.tasks.xlsx_to_oscal_profile/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.transforms.implementations.osco/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.transforms.implementations.tanium/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.transforms.implementations.xccdf/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.transforms.results/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.transforms.transformer_factory/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.transforms.transformer_helper/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/api_reference/trestle.transforms.transformer_singleton/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/contributing/DCO/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/contributing/github_actions_setup/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/contributing/mkdocs_contributing/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/contributing/plugins/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/contributing/trestle_oscal_object_model/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/contributing/website/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/plugins/compliance-trestle-fedramp/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/reference/third-party-result-schema-SCC/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/trestle_sample_workflow/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/continuous-compliance/continuous-compliance/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/task.csv-to-oscal-cd/transformation/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/task.ocp4-cis-profile-to-oscal-catalog/transformation/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/task.ocp4-cis-profile-to-oscal-cd/transformation/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/task.tanium-result-to-oscal-ar/transformation/ - 2024-07-15 + 2024-08-23 daily https://oscal-compass.github.io/compliance-trestle/tutorials/task.transformer-construction/transformer-construction/ - 2024-07-15 + 2024-08-23 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 004a9a7df559148d8ca1c34400976369ed94114d..499ceb5d75f942cae36d31b04490a4822f19d3e5 100644 GIT binary patch delta 1320 zcmV+@1=srd3it|tABzYGFR;jF0{?SqbY*Q}a4vXlYyjn*!EWO=5Qgvj6oK!u({vBp zBJmzl^x8w)GeMJMn+Zj#94fZoz9dB{PIt4w0_}l+4Fs}iiQt!^W;mQ7b^rO?+nW~( zY`l9|{jk1W-H=mW8+UkE{rShQ-KW*(?T7m@Sf+TBE_VDXusX&#{JhzmPNy}SNWC0* z?ZaWi>X=S=Qwuk@>z`KJ4>#$PE115O&%KeVBY$u5jo0-^j=k60yW6{u-R-CD?#FaV zExWo*9i=~zF25y!X{!49D)-=^#O}%##+Ua@;74L#Ug1p5`LeKPLHas9zI;+(K}I3MbgRR&=kPjaycfD z(0_2##glPQvMB&L7!hbsAzAnZXWg2edWXXI$$Zs=h?jvFi7FXp9GqmPabWf)se~~a z3)J7N;Rwg%r4}#J8Z9FsVI6Q_Qv1lFb-d(Kp&=zFk&i$)X|w<&qCjhD?X2s3K!Msx zCQ(!b3XzggCIvnpMY6H+a`twClS79Y;o`%TXOvw!OEywK&^%;2q1j5*808 zM)WnfA^1Hi8}opQR+D{H0^P1ogXS;<> zSxhuG;z9>BvicGZXPM_$@rK|PF$1d71rgU;^crmRUltPaTB@?$2^bYwEPp4vVwJVl zbz_>c#vhDtnXW?<++ZcnGgjl%Nlr=8Ur?w985l>q4`!g`z`-bpoNJqvUn=wV1xHS) z7|_Sg86GhXGYVH!LeB#k#eOIYbtuT)-}J)W?JFyg57FeaUzEU)Y-jr;&LVTp{v zgjnVs;P7^$fa`b*5YRZiRDVzwiZf^TUSzilkt>yt7Gm~dLc>}6UU^VfgD*HR%fBb0 z!OI>8X7YVucrezM=Jau%g2*75|9-1&n$A5btdKjX!QhJXp zvNCu%k{t+)3DL;C1q0Imv)(8>3ryK4(~E_QQNSjg%mOxJQKMLhIJ1sdP|H_BnhAdg z5Xb6$osW$>Sc;8Jy_PI|vm0aHUhJ30-`Z{bbfu^{qYb`&>kZBFI<%{@W?=?99!z67 zhHn7o*zz#`K$afB4T~%OQCb+rI&`8Rs37eEg5i5QgvjD+1qTXBS)a z16l7OMXx=yJrguJwwX|*%AsQW-cR`1uhs~d94YvT@|R)78ZTldrI^Y-1{7%Wq~Nf$dS{FD&R+UnuMB_6#K^;9ICJPu6(%q^E= z0ttT&H(fj!_aK`Bkb@C{_7swZUvSo~*{L@ue4or$J&1T2h>@t0VaCBpW*P@(Z<0zF zqp?8!%^HqyOkQg7B(2dh5)#${2PUiR`M8i_eR*lVo$%P#=~#WA>&xdDI3 z7ziaKb&ZuorGnYvfgRHYa8M?BKp_e|E@$w(x-!=cM>WV0jkLn=9!N#3Sp79;px!?r zVx_wjqQE%agr`KJpe=SS^GNpSf#q&%*=VhT}D>L5=d z-GzcPR{x9fGJg)_k^+eyCsJ65j1r|b6ey^0r#0>o@KNezc+~#nYC3g26V7XbL!9jv zHf1r<*oX@q(8%g*IGkmkui_2CD`Eyzr3)giwdgh2=)Wu^;$oM)`Yr<0tLqQ9U}4Kgr}b|1_@$$^7W5INU2E5B6c?Guii zQZb;9oijXQUWliTgu^s=Hb@$8ewMJ(sh+94HhVl_4PnGl>tRefJy~AaQyTdJYQhp3 zg9)+BJHX-XL;=_F79gN;dZ~Y)EEH$X?!Cxv6(UzEA1%b}#e{~l_Pz3;tOj3jV3vPR zM1z+-4$S2H!th|MEzRlUJOzB$uycS(1O#K!N?xpy=z_D}-rLTke=PoJ(3}2Maj6F1AkdA-%KJ+j|XQlKW zS!8AKawIzt7!#tAdkF@l|7X2Xb{3ejQKlCQ6{CPnIGF`(#-c{C5OHQ5ub`H%gftWW z1|W{rd!3JsJ6MX1O}&;Ze6t&4-d^n2``_Db{B)(LIin4}ed`6y@;bDuvSwihJ0479 zIfgF)=GgKy60A9f?Zr`;Uof3$mtO_i)*JR}NBa7wZcjSMzO5(z%C;O$&|ThS>C#O@ zoo;$xYxl?feOoW$8`ChxNXyGZ!!i#~#mR@qz4fO?Y4WpU+~`N{p09hOlNAL-A7`hk fE2}QUSjP05H-GrgVap+T6x)9Q#o>5glYIaH<7j(H diff --git a/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/index.html b/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/index.html index 4e53ccb9c..14c9eae98 100644 --- a/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/index.html +++ b/tutorials/ssp_profile_catalog_authoring/ssp_profile_catalog_authoring/index.html @@ -5341,6 +5341,7 @@

                                                                                    The au

                                                                                    Also note that the optional final sections are provided, and labeled using the title for the corresponding section.

                                                                                    In addition, this is the only control markdown where the moustache ({{}}) items have been replaced by the corresponding parameter values in the final resolved profile catalog, surrounded by brackets, so that the prose corresponds to the final intended control and its implementation.

                                                                                    The markdown can have guidance per-component in the control, as shown by the line, ### ACME Component. Any prose directly under a ## implementation section will apply to the overall system component, but sections in a sub-header of the form ### will only apply to that particular component.

                                                                                    +

                                                                                    The --include-all-parts flag controls how the main system component (This System) is written in the markdown. By default, control parts are not written out unless a component has a rule associated with that particular control part or statement. When --include-all-parts is set, all control parts will be written with the main component present under the ## Implementation for part <part> section. All other components will still be conditionally added based on the presence of rules.

                                                                                    After generating the markdown for the resolved profile catalog you may then edit the files and provide text in the sections with Add control implementation... in them. But do not remove the horizontal rule lines or modify/remove the lines with ### in them, corresponding to system components.

                                                                                    If you edit the control markdown files you may run ssp-generate again and your edits will not be overwritten. When writing out the markdown for a control, any existing markdown for that control will be read and the response text for each part will be re-inserted into the new markdown file. If the new markdown has added parts the original responses will be placed correctly in the new file, but if any part is removed from the source control json file then any corresponding prose will be lost after the next ssp-generate.